Skip to content

Add ability to give a form multiple templates of a given type and pick one by name through uiSchema #3962

@elevesque-nexapp

Description

@elevesque-nexapp

Prerequisites

What theme are you using?

core

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

In my project, we define a variety of schemas in our backend API and dynamically fetch those from the frontend to display relevant forms. In some of these forms, we have object fields that we would like to be able to display horizontally instead of vertically. Take for example an array of HTTP headers:

{
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "header" { "type": "string" },
      "value": { "type": "string" }
    }
  }
}

We would like to be able to display those side-by-side as below:
Screenshot 2023-11-16 at 3 42 26 PM

However, we have other object fields (the form itself being one example) for which we want to keep the default vertical layout.

Because schemas are defined on the backend, we can't easily provide a custom ObjectFieldTemplate for this field.

Describe the solution you'd like

We'd like to be able to provide multiple ObjectFieldTemplate implementations to our form (say VerticalObjectFieldTemplate and HorizontalObjectFieldTemplate) and have the ability to pick one from the ui schema. For example:

function MyForm() {
  const { schema, uiSchema } = useDynamicSchema()

  return <Form schema={schema} uiSchema={uiSchema} templates={{ ObjectFieldTemplate: {'vertical': VerticalObjectFieldTemplate, 'horizontal': HorizontalObjectFieldTemplate}} />

schema:

{
  "type": "object",
  "properties": {
    "headers": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "header" { "type": "string" },
          "value": { "type": "string" }
        }
      }
    }
  }
}

uiSchema:

{
  "headers": {
    "items": {
      "ui:ObjectFieldTemplate": "horizontal"
    }
  }
}

Describe alternatives you've considered

Our current solution is to do basically that, but by modifying the ui schema by replacing "ui:ObjectFieldTemplate": "horizontal" by its implementation in the frontend after fetching it from the backend. This works, but it's not exactly simple nor elegant.

We've also looked into custom widgets and fields, but the former is too low level and the latter appears too generic. With a custom field, we weren't able to get the object field's properties without digging around in the registry and form data in somewhat complex ways.

We've also considered the options of simply adding some arbitrary key to they ui schema and using that as a sort of additional prop to a custom ObjectFieldTemplate. It's simple enough, but it opens the door to all sorts of implicit contracts between backend and frontend that would be hard to track, maintain and debug.

We've also tried playing around with ui:classNames and ui:style, but between the various layers of Template, Field and Render components that don't always pass all props down to their children, this quickly ends up becoming confusing and finicky.

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureIs a feature requesthelp wantedtemplatesRelated to the templates capabilities of RJSF

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions