Radio Button type validation

Hi All,

So far in my application i’ve managed to avoid using the UI schema and have just gone with the the JSON forms defaults which I really like. It means I have one less file to maintain which makes changing my schema/UI way easier for me and my colleagues.

I’m trying to implement functionality that could be carried out by something like a radio button. I have two boolean properties on one of my objects. I want the validation to be that either one can be true while the other is false, or both can be false. Or more concisely, both cannot be true at the same time.

I’ve tried a few different combinations of if/else and allOf but haven’t been able to get to what I want. Do you have any suggestions for the best approach to achieve this without using UI schema.

Best regards,
James

Hi @james-morris,

the easiest way is to switch to an enum instead of two booleans. Then you can let the user select between all valid options. We also have a radio renderer for enums, so you can use that too. However to trigger the radio renderer you need to add options: { format: "radio" } to the respective Control element in the UI Schema.

To avoid maintaining a separate UI Schema file you can either

  • use the exported Generate.uiSchema(schema) to generate the default UI schema and then add the respective option to the relevant elements, or
  • (re)register the exported MaterialRadioGroupControl with a different tester which can detect the enums it shall be applied to. For example to automatically apply to all enums with less than 5 options or only to properties with a certain name.

If you’d like to stick to two booleans, then you also have multiple options. One possible validation for them could look like this:

{
  "type": "object",
  "properties": {
    "bool_1": {
      "type": "boolean"
    },
    "bool_2": {
      "type": "boolean"
    }
  },
  "allOf": [
    {
      "if": {
        "properties": {
          "bool_1": {
            "const": true
          }
        }
      },
      "then": {
        "properties": {
          "bool_2": {
            "const": false
          }
        }
      }
    },
    {
      "if": {
        "properties": {
          "bool_2": {
            "const": true
          }
        }
      },
      "then": {
        "properties": {
          "bool_1": {
            "const": false
          }
        }
      }
    }
  ]
}

Depending on your edge cases regarding undefined booleans you might want to add required properties to the if clauses and/or not statements to the then clauses.

This works, however the boolean renderers shipped with JSON Forms don’t show any errors. So if you want to see the produced error messages then you’ll need to provide custom boolean renderers. Note that the error messages will be very cryptic by default so you might want to also look into customizing them.

Instead of using validation, you could also use the rule support of JSON Forms to enable and disable the other checkbox when one of them is already enabled. For this you need to add the rules to the UI Schema. For how to specify these rules, please see this documentation. Of course then you need to either maintain a UI Schema file or add them programmatically as outline above.

Alternatively you could also write a custom renderer for the two booleans and just encode your enablement logic there or just render them as a radio control again.

Abstractly speaking it seems to me that an enum in the data better encodes the actual intention, especially if there might be more cases (booleans) in the future. Of course I don’t know your use cases so ymmv.