No rule validation for "array contains value" when array undefined

I have a JSON schema that basically looks like:

...
"properties: {
     "stringArray": {            
            "items": {
                "enum": ["Option1", "Option2", "Other"],
                "type": "string"
            },
            "type": "array"
      }
}

and a UI schema like:

{
      "type": "Control",
      "scope": "#/properties/dependentControl",
      "rule": {
            "effect": "ENABLE",
            "condition": {
              "scope": "#/properties/stringArray",
              "schema": { "contains": { "const": "Other" } }
            }
      }
},

So I can select multiple values for the stringArray component and when the stringArray property contains “Other” (e.g. stringArray = ["Option1", "Other"] or stringArray = ["Other"]) I want to ENABLE the dependentControl.

This fails if the stringArray is not set and then the dependentControl is always ENABLED. Once I selected an enum value for stringArray everything starts working as expected (I guess because the stringArray is now set). It also continues working when I remove all items from stringArray again.

I have similar logic where I enable a control when a simple string property matches a certain value. This works even if the string control is not set. So something is different when using an array…

Any idea why it fails for this specific array case? could be an AJV problem?

Not sure if this may help you, but try setting the “default” property to initialize as “Other”.
You may also need to add the “useDefaults” in the ajv handler.

1 Like

Hi @clemens-msupply,

In the cases were the behavior for not set properties does not match your expectation you can often just reverse the rule, i.e. design it as a DISABLE and revert the condition schema with a not.

In case you want to be more explicit or would like to have more control you can modify the condition scope to the parent scope, in your case # and then go into more detail in regards to stringArray itself, for example by setting it to required in the condition schema.

@dcjarvisvt’s suggestion works around the problem by always making sure that stringArray is defined, however I would recommend setting the default to the empty array.

1 Like

Thanks for your suggestions!

@dcjarvisvt I didn’t manage to fix it using AJV and some AJV options actually broke my UI so I didn’t follow it further, but thanks anyway!

@sdirix I am pretty sure I tried the reverse rule and it didn’t work for me. However, going one level up did the trick! thank you! Here is the working example:

        {
          "type": "Control",
          "scope": "#/properties/dependentControl",
          "rule": {
            "effect": "ENABLE",
            "condition": {
              "scope": "#",
              "schema": {
                "properties": {
                  "stringArray": { "contains": { "const": "Other"  }  }
                },
                "required": ["stringArray"]
              }
            }            
          }
        },

Is the JSONForms web site open source as well? Are you interested in letting me add some examples/sentences about rules? I mainly found rules hard because I didn’t know JSON schema well enough and how the condition works… After getting it I find it very cool now! great work!

@clemens-msupply I would find more documentation helpful as well. If you have further details, I would find it helpful.
I am specifically trying to enable a value based on another value. I know how to use the “const” value, but that is just 1 value. I would like to enable a value based on a range. For example > 0.
Any thoughts?

The rule condition schema is just an arbitrary JSON schema which is applied to the scope of the condition. This means if the scope value matches the condition JSON schema the rule is applied.

This is quite nice because you have all the power of JSON schema to define your conditions.

For example, you can just use normal JSON schema to have a condition > 0:

                   "rule": {
                        "condition": {
                            "schema": {
                                "minimum": 1
                            },
                            "scope": "#/properties/target"
                        },
                        "effect": "ENABLE"
                    },

@sdirix for this example I actually have the same problem as for the array case. When the target property is not defined yet it doesn’t work but it starts working once it becomes defined. I guess you can work around it in a similar way but its still a bit unexpected that it doesn’t work. Can’t this be handled on JSONForms side? e.g. if the scope property is not defined the rule automatically fails and AJV is not even called? but I might miss some other cases?

Is the JSONForms web site open source as well? Are you interested in letting me add some examples/sentences about rules? I mainly found rules hard because I didn’t know JSON schema well enough and how the condition works… After getting it I find it very cool now! great work!

Yes please, I would very much appreciate documentation improvements :heart: The repo can be found here: GitHub - eclipsesource/jsonforms2-website: JSON Forms 2 Website.

or this example I actually have the same problem as for the array case. When the target property is not defined yet it doesn’t work but it starts working once it becomes defined. I guess you can work around it in a similar way but its still a bit unexpected that it doesn’t work. Can’t this be handled on JSONForms side? e.g. if the scope property is not defined the rule automatically fails and AJV is not even called? but I might miss some other cases?

I’m open for extensions here. We just have to be careful in regards of backward compatibility. A compromise could be to add an enum, e.g. whenUndefined: 'fail' | 'success'.

1 Like

@clemens-msupply thanks for the help and explanation. This was very helpful.

1 Like