rjsf-team / react-jsonschema-form

A React component for building Web forms from JSON Schema.

Home Page:https://rjsf-team.github.io/react-jsonschema-form/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Implementation of Bootstrap grid layout into a custom field

toccoto opened this issue · comments

Description

Implementation of Bootstrap grid layout into a custom field

Hey, I've been looking at this library today, but really wanted to be able to control the grid layout of Schema, independent of how it's sent. (Basically the backend will send the schema independent of order, rows and columns) I came up with this, which works. Just wondering if there is a cleaner way I'm missing or if I'm on the right track. Thanks for the help!

import React from 'react';
import SchemaForm from 'react-jsonschema-form';
import ObjectField from 'react-jsonschema-form/lib/components/fields/ObjectField';
import {retrieveSchema} from "react-jsonschema-form/lib/utils";
import {Grid, Row, Col} from 'react-bootstrap';

class GridField extends ObjectField {
  constructor(props) {
    super(props);
  }

  render() {
    const {
      uiSchema,
      errorSchema,
      idSchema,
      name,
      required,
      disabled,
      readonly,
      onBlur
    } = this.props;
    const {definitions, fields, formContext} = this.props.registry;
    const {SchemaField, TitleField, DescriptionField} = fields;
    const schema = retrieveSchema(this.props.schema, definitions);
    const title = (schema.title === undefined) ? name : schema.title;
    const order = uiSchema['ui:options'].order;
    return (
      <fieldset>
        {title ? <TitleField
            id={`${idSchema.$id}__title`}
            title={title}
            required={required}
            formContext={formContext}/> : null}
        {schema.description ?
          <DescriptionField
            id={`${idSchema.$id}__description`}
            description={schema.description}
            formContext={formContext}/> : null}
        {
          order.map((row, index) => {
            return (
              <div className="row" key={index}>
                {
                  Object.keys(row).map((name, index) => (
                    <Col {...row[name]} key={index}>
                      <SchemaField
                                   name={name}
                                   required={this.isRequired(name)}
                                   schema={schema.properties[name]}
                                   uiSchema={uiSchema[name]}
                                   errorSchema={errorSchema[name]}
                                   idSchema={idSchema[name]}
                                   formData={this.state[name]}
                                   onChange={this.onPropertyChange(name)}
                                   onBlur={onBlur}
                                   registry={this.props.registry}
                                   disabled={disabled}
                                   readonly={readonly}/>
                    </Col>
                  ))
                }
              </div>
            );
          })
        }</fieldset>
    );
  }
}

const fields = {
  grid: GridField,
};

const schema = {
  title: "Primary Applicant",
  type: "object",
  properties: {
    personal: {
      title: "",
      type: "object",
      properties: {
        first: {
          type: "string",
          title: "First"
        },
        mi: {
          type: "string",
          title: "MI"
        },
        last: {
          type: "string",
          title: "Last"
        },
        suffix: {
          type: "string",
          title: "Suffix",
          enum: ['jr', 'sr'],
          enumNames: ['JR', 'SR']
        },
        ssn: {
          type: "string",
          title: "ssn"
        },
        dob: {
          type: "string",
          title: "dob"
        }
      }
    }
  }
};

const getUiSchema = () => {

  let order = [
    {
      first: { md: 5 },
      mi: { md: 2 },
      last: { md: 5 }
    },
    {
      suffix: { md: 2 },
      ssn: { md: 5 },
      dob: { md: 5 }
    }
  ]

  return  {
    personal: {
      "ui:field": "grid",
      "ui:options": {
        "order": order
      }
    }
  }
}

export const Applicant = () => (
  <div>
    <h1>Applicant</h1>
    <SchemaForm schema={schema} uiSchema={getUiSchema()} fields={fields}/>
  </div>
);

Sorry, I couldn't get it working on jsFiddle but the end result works. I get 2 rows, with split columns.

Basically I just extend ObjectField, and add the data to split up based on the ordering info.

Any other suggestions are welcome.

Object fields are orderable using the ui:order uiSchema directive.