Hide Nested Fields In Array

Hello, sorry if this is a duplicate and my brain just isn’t working.

Imagine I have a schema like so:

{
  "type": "object",
  "title": "Person",
  "properties": {
    "friends": {
      "type": "array",
      "items": {
        "type": "object",
        "title": "Friend",
        "properties": {
          "name": {
            "type": "string"
          },
          "isBestField": {
            "type": "boolean"
          },
          "dob": {
            "type": "string",
            "format": "date"
          }
        }
      }
    }
  }
}

and a UISchema

{
  "type": "Control",
  "scope": "#/properties/friends"
}

If I wanted to show the DOB field only when isBestFriend is selected, is that possible?

I’ve tried using

It appears that I cannot.

Please note, I am capable of downloading the source code and modifying things. I am ok with hard coding things. I just need this for a specific project where the schema is predetermined.

Thank you!

Hi @dclark27,

This UI Schema should do the trick:

{
  "type": "VerticalLayout",
  "elements": [
    {
      "type": "Control",
      "scope": "#/properties/friends",
      "options": {
        "detail": {
          "type": "VerticalLayout",
          "elements": [
            {
              "type": "Control",
              "scope": "#/properties/name"
            },
            {
              "type": "Control",
              "scope": "#/properties/isBestField"
            },
            {
              "type": "Control",
              "scope": "#/properties/dob",
              "rule": {
                "effect": "SHOW",
                "condition": {
                  "scope": "#/properties/isBestField",
                  "schema": {
                    "const": true
                  }
                }
              }
            }
          ]
        }
      }
    }
  ]
}

Note that the JSON Forms editor is a nice showcase but it’s horribly outdated. So I would recommend the JSON Forms React seed or the example applications in the main repo to play around.

Thanks Stefan!

Another question in the same vein. We utilize lots of definitions in our schemas and then render them as properties in the schema. For example:

{
  "title": "Commercial Auto Insurance",
  "type": "object",
  "definitions": {
    "AgencyDetails": {
      "title": "Agency Details",
      "type": "object",
      "definitions": {},
      "required": [
        "agencyName",
        "agencyPhone",
        "agencyFax",
        "agencyCode",
        "agencySubCode",
        "agencyCustomerId"
      ],
      "properties": {
        "agencyName": {
          "title": "Agency",
          "type": "string",
          "maxLength": 20000
        },
        "agencyPhone": {
          "title": "Agency Phone ext",
          "type": "string",
          "maxLength": 20000
        },
        "agencyFax": {
          "title": "Agency Fax",
          "type": "string",
          "maxLength": 20000
        },
        "agencyCode": {
          "title": "Agency Code",
          "type": "string",
          "maxLength": 20000
        },
        "agencySubCode": {
          "title": "Producer Code",
          "type": "string",
          "maxLength": 20000
        },
        "agencyCustomerId": {
          "title": "Agency Customer ID",
          "type": "string",
          "maxLength": 20000
        }
      }
    }
  },
  "required": [],
  "properties": {
    "agencyDetails": {
      "title": "Agency Details",
      "$ref": "#/definitions/AgencyDetails"
    }
  }
}

When generating a UISchema, using the generateDefaultUISchema function, all it spits out is:

{
  "type": "VerticalLayout",
  "elements": [
    {
      "type": "Control",
      "scope": "#/properties/agencyDetails"
    }
  ]
}

If I wanted to apply those options (hiding / showing based on siblings data) via a UISchema, what would that UISchema look like?

I’ve tried a few iterations (passing the definition to the generateDefaultUISchema function and appending to the UISchema, for example:

{
  "type": "VerticalLayout",
  "elements": [
    {
      "type": "Control",
      "label": "Agency Details",
      "scope": "#/properties/agencyDetails",
      "elements": [
        {
          "type": "Control",
          "scope": "#/properties/agencyName",
          "options": {
            "readonly": true
          }
        },
        {
          "type": "Control",
          "scope": "#/properties/agencyPhone"
        },
        {
          "type": "Control",
          "scope": "#/properties/agencyFax"
        },
        {
          "type": "Control",
          "scope": "#/properties/agencyCode"
        },
        {
          "type": "Control",
          "scope": "#/properties/agencySubCode"
        },
        {
          "type": "Control",
          "scope": "#/properties/agencyCustomerId"
        }
      ]
    }
  ]
}

This appears to work, but adding things like an options object to my fields but nothing takes affect. I have a hunch the type “Control” ignores the elements array of the UISchema.

Is there any way to have UISchema control over these fields if they’re defined in this manner? Or do I need to restructure my schema?

Thanks for your help! This library is amazing and we’ve been using it in production for over a year now.

Hi @dclark27,

Our Ui Schema generator only produces “shallow” UI Schemas, i.e. a single vertical layout with a Control for every property of an object.

The renderers for objects and arrays then determine the UI Schema for their nested properties. They do this by:

  • Checking whether the UI Schema has an options.detail field
  • Checking the uischemas registry for a UI schema for them
  • Generate a default UI Schema

To use the first option, you need to slightly modify your UI Schema

{
  "type": "VerticalLayout",
  "elements": [
    {
      "type": "Control",
      "label": "Agency Details",
      "scope": "#/properties/agencyDetails",
      "options": {
        "detail": {
          "type": "VerticalLayout",
          "elements": [
            {
              "type": "Control",
              "scope": "#/properties/agencyName",
              "options": {
                "readonly": true
              }
            },
            {
              "type": "Control",
              "scope": "#/properties/agencyPhone"
            },
            {
              "type": "Control",
              "scope": "#/properties/agencyFax"
            },
            {
              "type": "Control",
              "scope": "#/properties/agencyCode"
            },
            {
              "type": "Control",
              "scope": "#/properties/agencySubCode"
            },
            {
              "type": "Control",
              "scope": "#/properties/agencyCustomerId"
            }
          ]
        }
      }
    }
  ]
}

Thanks again for this! I am almost done with this tricky configuration.

Is it possible to combine the two answers from above? I.e., add a rule for a field nested in a UISchema.

I’ve tried a few different ways here. The first I append options.detail.rule to a field, the other I append just rule.

{
  "type": "VerticalLayout",
  "elements": [
    {
      "type": "Control",
      "label": "Agency Details",
      "scope": "#/properties/agencyDetails",
      "options": {
        "detail": {
          "type": "VerticalLayout",
          "elements": [
            {
              "type": "Control",
              "scope": "#/properties/agencyName",
              "options": {
                "readonly": true // this works!
              }
            },
            {
              "type": "Control",
              "scope": "#/properties/agencyPhone",
              "options": {
                "detail": {
                  "rule": {
                    "effect": "HIDE", // this does not!
                    "condition": {
                      "scope": "#/properties/agencyName",
                      "schema": {
                        "const": "hide"
                      }
                    }
                  }
                }
              }
            }
          ]
        }
      }
    }
  ]
}
{
  "type": "VerticalLayout",
  "elements": [
    {
      "type": "Control",
      "label": "Agency Details",
      "scope": "#/properties/agencyDetails",
      "options": {
        "detail": {
          "type": "VerticalLayout",
          "elements": [
            {
              "type": "Control",
              "scope": "#/properties/agencyName",
              "options": {
                "readonly": true // this works!
              }
            },
            {
              "type": "Control",
              "scope": "#/properties/agencyPhone",
              "rule": { // this does not!
                "effect": "HIDE",
                "condition": {
                  "scope": "#/properties/agencyName",
                  "schema": {
                    "const": "hide"
                  }
                }
              }
            }
          ]
        }
      }
    }
  ]
}

Neither seem to work (even with omitting the condition and setting to {} as others have suggested to always hide a field. Perhaps it needs to live at the root of the Control element above?