How to add conditional required validation on nested object controls?

I am using version 2.5.1 with react material renderer, with custom renderers for string, number, radio, and date.

I have schema like

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    },
    "married": {
      "type": "string",
      "enum": [
        "Married",
        "Single"
      ]
    },
    "child": {
      "type": "object",
      "properties": {
        "child_name": {
          "type": "string"
        },
        "child_married": {
          "type": "string",
          "enum": [
            "Married",
            "Single"
          ]
        },
        "child_address": {
          "type": "string"
        },
        "grandChild": {
          "type": "object",
          "properties": {
            "grand_child_name": {
              "type": "string"
            },
            "grand_child_married": {
              "type": "string",
              "enum": [
                "Married",
                "Single"
              ]
            },
            "grand_child_city": {
              "type": "string"
            },
          }
        }
      }
    }
  }
}

Following are the rules we need to implement

  1. /properties/name , /properties/married are always visible and required
  2. If properties/married is = “Married”
    then /properties/child/child_married, /properties/child/ child_name, /properties/child/ child_name are visible and required.
  3. If properties/child/child_married = “Married”
    then /properties/child/grandChild/grand_child_married,
    /properties/child/grandChild/grand_child_married,
    /properties/child/grandChild/grand_child_city Are visible and required.

I was able to show/hide the respective properties based on the enum values in uischema using rules.
The problem I am facing is how to conditionally add the required property to the schema at such a deeply nested level?

Hi!

This can be expressed using JSON Schema’s if/then/else support, e.g.

{
  "type": "object",
  "required": [
    "name",
    "married"
  ],
  "if": {
    "properties": {
      "married": {
        "const": "Married"
      }
    }
  },
  "then": {
    "properties": {
      "child": {
        "required": [
          "child_name",
          "child_married"
        ]
      }
    }
  },
  "properties": {
    "name": {
      "type": "string"
    },
    "married": {
      "type": "string",
      "enum": [
        "Married",
        "Single"
      ]
    },
    "child": {
      "type": "object",
      "if": {
        "properties": {
          "child_married": {
            "const": "Married"
          }
        }
      },
      "then": {
        "properties": {
          "grandChild": {
            "required": [
              "grand_child_name",
              "grand_child_married"
            ]
          }
        }
      },
      "properties": {
        "child_name": {
          "type": "string"
        },
        "child_married": {
          "type": "string",
          "enum": [
            "Married",
            "Single"
          ]
        },
        "child_address": {
          "type": "string"
        },
        "grandChild": {
          "type": "object",
          "properties": {
            "grand_child_name": {
              "type": "string"
            },
            "grand_child_married": {
              "type": "string",
              "enum": [
                "Married",
                "Single"
              ]
            },
            "grand_child_city": {
              "type": "string"
            }
          }
        }
      }
    }
  }
}

Note that the child and grandChild objects need to exist as otherwise there will be no errors reported against them, e.g.

{
  "name": "Foo",
  "married": "Married"
}

is valid while

{
  "name": "Foo",
  "married": "Married",
  "child": { }
}

is not.

Of course you could also add them to the then blocks, e.g.

{
  "then": {
    "required": ["child"],
    "properties": {
      "child": {
        "required": [
          "child_name",
          "child_married"
        ]
      }
    }
  }
}

However these errors will not show up in the JSON Forms UI by default. To show the errors on the actual field the objects need to exist as described above.