Search code examples
javascriptreactjsreact-jsonschema-forms

Using anyOf to see objects name?


I have a schema here where I would like to have a drop down, to select an option, and from there - depending on the selection different options appear; all being nested within an array to have multiples of them.

I have noticed that when I am filling in with dummy data, the output json isnt storing the name of the selected option

so the data.json looks something like this:

{
  "page1": [
    {
      "imageOptions": {
        "imageHeightType": "vh",
        "imageHeight": 50
      },
      "textboxArea": {
        "headerText": "Header for selection1",
        "headingTag": "h1",
        "textBoxOpacity": 15
      }
    },
    {
      "content": "This is a complety different selection, yet there is no name to tell the difference between these two difference objects"
    }
  ]
}

As you can see theres no object to wrap these two different items within the page1 array - Ideally would like something like:

{
  "page1": [
    {
     // Title of object goes here from schema
      "imageOptions": {
        "imageHeightType": "vh",
        "imageHeight": 50
      },
      "textboxArea": {
        "headerText": "Header for selection1",
        "headingTag": "h1",
        "textBoxOpacity": 15
      }
    },
    {
      // Title of object goes here from schema
      "content": "This is a completely different selection, yet there is no name to tell the difference between these two difference objects"
    }
  ]
}

Is there a way to make this so? I have looked on the docs for AnyOf but not much luck. Quite new to React-JsonSchema-Forms.

Below is my current Schema:

{
  "type": "object",
  "properties": {
    "page1": {
      "type": "array",
      "items": {
        "type": "object",
        "anyOf": [
          {
            "title": "Full Width Image",
            "type": "object",
            "properties": {
              "imageOptions": {
                "type": "object",
                "title": "Image",
                "properties": {
                  "image": {
                    "type": "string",
                    "title": "Image",
                    "format": "data-url"
                  },
                  "imageHeightType": {
                    "enum": [
                      "px",
                      "vh"
                    ]
                  },
                  "imageHeight": {
                    "type": "number",
                    "title": "Image Height"
                  }
                }
              },
              "textboxArea": {
                "type": "object",
                "title": "Textbox Area",
                "properties": {
                  "headerText": {
                    "type": "string",
                    "title": "Heading Text"
                  },
                  "headingTag": {
                    "enum": [
                      "h1",
                      "h2",
                      "h3"
                    ]
                  },
                  "imageText": {
                    "type": "string",
                    "title": "Body Text"
                  },
                  "textboxPosition": {
                    "title": "Textbox Position",
                    "enum": [
                      "Left",
                      "Center",
                      "Right"
                    ]
                  },
                  "textboxColor": {
                    "title": "Color of Textbox Area",
                    "type": "string"
                  },
                  "textBoxOpacity": {
                    "title": "Textbox Opacity %",
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100,
                    "multipleOf": 5
                  }
                }
              }
            }
          },
          {
            "title": "Custom Block",
            "type": "object",
            "properties": {
              "content": {
                "type": "string"
              }
            }
          }
        ]
      }
    }
  }
}

Also Link to the online schema editor if it helps understand my issue


Solution

  • Why not just add a name-like property to each object? You can then hide/disable it if you want:

    schema:

    "anyOf": [
        {
            "title": "Full Width Image",
            "type": "object",
            "properties": {
                "name": {
                    "type": "string",
                    "default": "fullWidthImage"
                },
                "imageOptions": {
                    "type": "object",
                    "title": "Image",
                    "properties": {...}
                    ...
                }
                ...
            }
        },
        {
            "title": "Custom Block",
            "type": "object",
            "properties": {
                "name": {
                    "type": "string",
                    "default": "custom"
                },
                "content": {
                    "type": "string"
                }
            }
        }
    ]
    

    uiSchema:

    {
        "page1": {
        "items": {
            "name": {
                "ui:widget": "hidden"
            },
            "imageOptions": {...},
            ...
        }
    }
    

    formData then should look like this:

    {
        "page1": [
            {
                "name": "fullWidthImage",
                "imageOptions": {
                    "imageHeightType": "vh",
                    "imageHeight": 50
                },
                "textboxArea": {
                    "headerText": "Header for selection1",
                    "headingTag": "h1",
                    "textBoxOpacity": 15
                }
            },
            {
                "name": "custom",
                "content": "This is a complety different selection, yet there is no name to tell the difference between these two difference objects"
            }
        ]
    }