Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Having Layouts Horizontal/Vertical #3840

Open
1 task done
indersj opened this issue Aug 23, 2023 · 5 comments
Open
1 task done

Having Layouts Horizontal/Vertical #3840

indersj opened this issue Aug 23, 2023 · 5 comments
Labels
feature Is a feature request

Comments

@indersj
Copy link

indersj commented Aug 23, 2023

Prerequisites

What theme are you using?

core

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

I have read about the ObjectFieldTemplate, where the layout can be customized. But the question is will there be a feature of having a layout controlling the form vertically/horizontally and Categorization as per the schema config?

Describe the solution you'd like

const uischema = {
type: 'VerticalLayout',
elements: [
{
type: 'Control',
label: false,
scope: '#/properties/done',
},
{
type: 'Control',
scope: '#/properties/name',
},
{
type: 'HorizontalLayout',
elements: [
{
type: 'Control',
scope: '#/properties/due_date',
},
{
type: 'Control',
scope: '#/properties/recurrence',
},
],
},
],
};

Describe alternatives you've considered

What I am trying to suggest below jsonforms layouts.

https://jsonforms.io/examples/layouts

@indersj indersj added feature Is a feature request needs triage Initial label given, to be assigned correct labels and assigned labels Aug 23, 2023
@nickgros
Copy link
Contributor

I think @heath-freenome has an idea for how this may be implemented, but I don't think it's on our radar yet.

This issue includes references to many other issues that show how other RJSF users have made this work in the past: #3261

@nickgros nickgros removed the needs triage Initial label given, to be assigned correct labels and assigned label Aug 25, 2023
@aularon
Copy link
Contributor

aularon commented Sep 22, 2023

You can use rjsf-layout (released to public today) to achieve what you're after:

import Form, { Field } from "rjsf-layout";

<Form {...props}>
  <Field name="done" />
  <Field name="name" />
  <div style={{ display: "flex" }}>
    <Field name="due_date" />
    <Field name="recurrence" />
  </div>
</Form>

I developed it specifically to address this class of needs. Check documentation for further goodies.

@nagaozen
Copy link

I've implemented this way to provide a way to be customizable by uiSchema:

import { useMemo } from 'react'
import { canExpand, descriptionId, getTemplate, getUiOptions, titleId } from '@rjsf/utils'

/** The LayoutFieldTemplate` is the template to use to render all the inner properties of an object along with the
 * title and description if available. If the object is expandable, then an `AddButton` is also rendered after all
 * the properties.
 *
 * @param props - The `LayoutFieldTemplateProps` for this component
 */
export default function LayoutFieldTemplate (props) {
  const {
    description,
    disabled,
    formData,
    idSchema,
    onAddClick,
    properties,
    readonly,
    registry,
    required,
    schema,
    title,
    uiSchema
  } = props
  const options = getUiOptions(uiSchema)
  const TitleFieldTemplate = getTemplate('TitleFieldTemplate', registry, options)
  const DescriptionFieldTemplate = getTemplate('DescriptionFieldTemplate', registry, options)
  // Button templates are not overridden in the uiSchema
  const {
    ButtonTemplates: { AddButton }
  } = registry.templates

  const layout = uiSchema['ui:layout']
  const map = useMemo(() => properties.reduce((o, x) => ({ ...o, [x.name]: x }), {}), [properties])

  return (
    <fieldset id={idSchema.$id}>
      {title && (
        <TitleFieldTemplate
          id={titleId(idSchema)}
          title={title}
          required={required}
          schema={schema}
          uiSchema={uiSchema}
          registry={registry}
        />
      )}
      {description && (
        <DescriptionFieldTemplate
          id={descriptionId(idSchema)}
          description={description}
          schema={schema}
          uiSchema={uiSchema}
          registry={registry}
        />
      )}
      {layout.map((row, i) => (
        <div key={`L${i}j`} className='row'>
          {Object.keys(row).map((name, j) => (
            <div key={`L${i}${j}`} className={row[name].classNames}>
              {map[name].content}
            </div>
          ))}
        </div>
      ))}
      {canExpand(schema, uiSchema, formData) && (
        <AddButton
          className='object-property-expand'
          onClick={onAddClick(schema)}
          disabled={disabled || readonly}
          uiSchema={uiSchema}
          registry={registry}
        />
      )}
    </fieldset>
  )
}

Usage:

{
  schema: {
    title: 'A registration form',
    description:
      'This is the same as the simple form, but with an altered bootstrap grid. Set the theme to default, and try shrinking the browser window to see it in action.',
    type: 'object',
    required: ['firstName', 'lastName'],
    properties: {
      firstName: {
        type: 'string',
        title: 'First name'
      },
      lastName: {
        type: 'string',
        title: 'Last name'
      },
      telephone: {
        type: 'string',
        title: 'Telephone',
        minLength: 10
      },
      email: {
        type: 'string',
        format: 'email',
        title: 'Email'
      }
    }
  },
  uiSchema: {
    ObjectFieldTemplate: LayoutFieldTemplate,
    'ui:layout': [
      {
        firstName: { classNames: 'col-md-6' },
        lastName: { classNames: 'col-md-6' }
      },
      {
        email: { classNames: 'col-md-6' },
        telephone: { classNames: 'col-md-6' }
      }
    ]
  },
  formData: {}
}

Issue related to #3695.

@billycrid
Copy link

@nagaozen - Your example works perfect in a scenario where your schema is just one level of strings/numbers etc. Did you have any example of how this would work with multiple objects at child level? For example with a schema like such...

{ title: 'A registration form', description: 'This is the same as the simple form, but with an altered bootstrap grid. Set the theme to default, and try shrinking the browser window to see it in action.', type: 'object', required: ['firstName', 'lastName'], properties: { firstName: { type: 'string', title: 'First name' }, lastName: { type: 'string', title: 'Last name' }, telephone: { type: 'string', title: 'Telephone', minLength: 10 }, email: { type: 'string', format: 'email', title: 'Email' }, testObject: { type: 'object', title: 'Testing an Object', properties: { foo: { type: 'string', title: 'foo' }, bar: { type: 'string', title: 'bar' } } } } }

with this schema, the code will break

@nagaozen
Copy link

@nagaozen - Your example works perfect in a scenario where your schema is just one level of strings/numbers etc. Did you have any example of how this would work with multiple objects at child level? For example with a schema like such...

{ title: 'A registration form', description: 'This is the same as the simple form, but with an altered bootstrap grid. Set the theme to default, and try shrinking the browser window to see it in action.', type: 'object', required: ['firstName', 'lastName'], properties: { firstName: { type: 'string', title: 'First name' }, lastName: { type: 'string', title: 'Last name' }, telephone: { type: 'string', title: 'Telephone', minLength: 10 }, email: { type: 'string', format: 'email', title: 'Email' }, testObject: { type: 'object', title: 'Testing an Object', properties: { foo: { type: 'string', title: 'foo' }, bar: { type: 'string', title: 'bar' } } } } }

with this schema, the code will break

Could you please clarify what you mean by breaking code? We deeply believe in this project and use it in production. None of our contributions seems to break with nested objects.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Is a feature request
Projects
None yet
Development

No branches or pull requests

5 participants