Skip to content

For arrays, don't assign a default value of an empty array. #3880

@abdalla-rko

Description

@abdalla-rko

Prerequisites

What theme are you using?

core

Is your feature request related to a problem? Please describe.

When you have a multiSelect/array field, by default an empty array will be assigned to the array field in the formData. If we try to submit a required empty multiSelect, the form will be submitted because AJV8 doesn't recognize it as empty and doesn't show validation errors. To avoid this behavior, we can currently set the emptyObjectFields to skipDefault, but this will skip all default values in the schema for example also for a string input that has default property.

Demonstration of the issue:

{
  "type": "object",
  "required": [
    "requiredMultiSelect",
    "requiredStringInput"
  ],
  "properties": {
    "multiSelect": {
      "type": "array",
      "title": "Multiple Select Input",
      "items": {
        "type": "string",
        "enum": [
          "option1",
          "option2"
        ]
      },
      "uniqueItems": true
    },
    "requiredMultiSelect": {
      "type": "array",
      "title": "Required multiple Select Input",
      "items": {
        "type": "string",
        "enum": [
          "option1",
          "option2"
        ]
      },
      "uniqueItems": true
    },
    "stringInput": {
      "type": "string",
      "default": "Hello"
    },
    "requiredStringInput": {
      "type": "string",
      "default": "Hello"
    }
  }
}

The formData results from different options of emptyObjectFields (Demo link).

  1. populateAllDefaults (Legacy):
{
  "multiSelect": [],
  "requiredMultiSelect": [],
  "stringInput": "Hello",
  "requiredStringInput": "Hello"
}

Raw Validate response: no AJV errors encountered.

  1. populateRequiredDefaults.
{
  "requiredMultiSelect": [],
  "requiredStringInput": "Hello"
}

Raw Validate response: no AJV errors encountered.

  1. skipDefaults
{}

Raw Validate response:

{
  "errors": [
    {
      "instancePath": "",
      "schemaPath": "#/required",
      "keyword": "required",
      "params": {
        "missingProperty": "requiredMultiSelect"
      },
      "message": "must have required property 'requiredMultiSelect'",
      "schema": [
        "requiredMultiSelect",
        "requiredStringInput"
      ],
      "parentSchema": {
        "type": "object",
        "required": [
          "requiredMultiSelect",
          "requiredStringInput"
        ],
        "properties": {
          "multiSelect": {
            "type": "array",
            "title": "Multiple Select Input",
            "items": {
              "type": "string",
              "enum": [
                "option1",
                "option2"
              ]
            },
            "uniqueItems": true
          },
          "requiredMultiSelect": {
            "type": "array",
            "title": "Required multiple Select Input",
            "items": {
              "type": "string",
              "enum": [
                "option1",
                "option2"
              ]
            },
            "uniqueItems": true
          },
          "stringInput": {
            "type": "string",
            "default": "Hello"
          },
          "requiredStringInput": {
            "type": "string",
            "default": "Hello"
          }
        }
      },
      "data": {}
    },
    {
      "instancePath": "",
      "schemaPath": "#/required",
      "keyword": "required",
      "params": {
        "missingProperty": "requiredStringInput"
      },
      "message": "must have required property 'requiredStringInput'",
      "schema": [
        "requiredMultiSelect",
        "requiredStringInput"
      ],
      "parentSchema": {
        "type": "object",
        "required": [
          "requiredMultiSelect",
          "requiredStringInput"
        ],
        "properties": {
          "multiSelect": {
            "type": "array",
            "title": "Multiple Select Input",
            "items": {
              "type": "string",
              "enum": [
                "option1",
                "option2"
              ]
            },
            "uniqueItems": true
          },
          "requiredMultiSelect": {
            "type": "array",
            "title": "Required multiple Select Input",
            "items": {
              "type": "string",
              "enum": [
                "option1",
                "option2"
              ]
            },
            "uniqueItems": true
          },
          "stringInput": {
            "type": "string",
            "default": "Hello"
          },
          "requiredStringInput": {
            "type": "string",
            "default": "Hello"
          }
        }
      },
      "data": {}
    }
  ]
}
  1. What I would like to get:
{
  "stringInput": "Hello",
  "requiredStringInput": "Hello"
}

Describe the solution you'd like

Introduce a new option for emptyObjectFields. For example skipEmptyDefaults, which will not assign an empty array to an array/multiSelect field. It will still apply the default value if we have a default property present in your schema.

<Form 
  experimental_defaultFormStateBehavior={{
    emptyObjectFields: "skipEmptyDefaults"
}}
/>

What do you think about this?

Describe alternatives you've considered

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions