react-easel

    0.0.14 • Public • Published

    React Easel

    A react component to dynamically build reusable forms. See the demo here

    Acknowledgements

    React Uniform Builder is built on top of uniforms and simple-schema with styling inspiration from formBuilder

    This project is maintained by Amdirent, Inc. If you'd like to build forms that hook up to arbitrary processes, and a dynamically created database table, check out Amdirent Opslab

    Usage

    Installing

    npm install --save react-easel
    

    or

    yarn add react-easel
    

    Quick Start

    First, ensure you have loaded bootstrap4 css. This library can be used with custom components and custom styling, but defaults exist for bootstrap.

    import Easel, { defaults } from 'react-easel';
     
    <Easel onSchemaChange={console.log} {...defaults.bootstrap4} />

    Using onSchemaChange, you can extract a json defintion of a SimpleSchema, which can then be used to render the form like so:

    import AutoFields from 'uniforms-bootstrap4';
    import { defaults } from 'react-easel';
    import SimpleSchema from 'node-simpl-schema';
     
    const AutoForm = defaults.bootstrap4.AutoForm;
    const AutoField = defaults.bootstrap4.AutoField;
     
    const jsonSchemaDef = <your json definition of a SimpleSchema>
     
    <AutoForm model={{}} schema={new SimpleSchema(jsonSchemaDef)} onSubmit={console.log}>
      <AutoFields autoField={AutoField} />
    </AutoForm>

    Note: onSchemaChange exists to get data out. It should not be used to drive Easel like a normal controlled component. Easel will populate initial values with props.schema, but it does not update on componentWillReceiveProps. This is because the process of creating Easel's interanal state from a schema is slow, but onSchemaChange is called every time a component is rearanged. Using this like a normal controlled component leads to a laggy drag and drop experience.

    Defining Your Own Components/Inputs

    Defaults exist for bootstrap4. You can see those in src/bootstrap4/defaults

    The easel component expects five props:

    Argument Description
    AutoForm A uniforms AutoForm. Can import directly from your uniforms package of choice, or use a custom form
    components A list of component definitions that will appear in the sidebar to be used on the form builder
    AutoField A uniforms AutoField component capable of rendering all the specified components. This will receive a prop componentType, which you can use to decide which component to render.
    onSchemaChange A callback function that will receive a json representation of the SimpleSchema when the component changes. This SimpleSchema can be used to render future forms.
    schema (optional) A json representation of an existing SimpleSchema to render.

    Component Definiton

    Components are defined as follows:

    Argument Type Description
    type string A unique identifier for the component. Ex: 'Text Field'
    schema object Corresponds to the node-simple-schema definition. Should, at the very least, contain type
    sidebar object The definition for what will show in the sidebar
    sidebar.text string The text that shows up on the sidebar. Ex: 'Text Field'
    sidebar.icon React Component The icon that shows up in the sidebar. Ex: <i className="fa fa-pencil" />
    admin object Definition of any additional configuration the field has. Defaults include name, placeholder, label, optional, and value
    admin.schema SimpleSchema A Simple Schema definition to render configuration fields for this Component. Whatever is filled into these fields will be passed as a prop to the component

    Example: Using react-select instead of a regular select

    First, make a uniforms driven react-select component:

    import React from 'react';
    import connectField from 'uniforms/connectField';
    import UnconnectedReactSelect from 'react-select';
    import wrapField from 'uniforms-bootstrap4/wrapField';
     
    const ReactSelect = connectField((props) => wrapField(props,
      <UnconnectedReactSelect {...props} onChange={e => props.onChange(? e.value : null)} />
    ));
     
    export default ReactSelect;

    Now, override the Select field in the bootstrap defaults with your custom select field:

    import Easel, { defaults } from 'react-easel';
    import ReactSelect from './ReactSelectUniforms';
     
    const myDefaults = { ...defaults.bootstrap4 };
    myDefaults.components = defaults.bootstrap4.map(component => {
      if (component.type === 'Select') {
        return {
          ...component,
          formElement: ReactSelect
        }
      }
      
      return component;
    });
     
    <Easel onSchemaChange={console.log} {...myDefaults} />

    Example: Adding a WYSIWYG editor

    For this example, we're going to use Trumbowyg.

    First, make the Uniforms driven component:

    import React from 'react';
    import $ from 'jquery';
    import wrapField from 'uniforms-bootstrap4/wrapField';
    import connectField from 'uniforms/connectField';
    import 'react-trumbowyg/dist/trumbowyg.min.css'
     
    global.$ = global.jQuery = window.$ = window.jQuery = $;
     
    const Trumbowyg = require('react-trumbowyg').default;
     
    let id = 0;
     
    // Made to only load the first value passed, that way trumbo can do its thing.
    class MyTrumboWyg extends React.Component {
      constructor(props, context) {
        super(props, context);
     
        this.state = {
          data: props.value
        }
      }
     
      render() {
        const props = this.props;
     
        return <Trumbowyg
          id={"react-trumbowyg" + (++id)}
          placeholder={props.placeholder}
          data={this.state.value}
          onChange={(e) => {
            props.onChange($(e.target).trumbowyg('html'));
          }}
        />
      }
    }
     
    export default connectField(props => wrapField(props,
      <MyTrumboWyg {...props} />
    ));

    Now, create your easel:

    import BaseField from 'uniforms-bootstrap4/AutoField';
    import Easel, { defaults } from 'react-easel';
    import MyTrumboWyg from './MyTrumboWyg';
     
    // A custom auto field capable of using `componentType` to decide to render the WYSIWYG
    class CustomAuto extends BaseField {
      getChildContextName() {
        return this.context.uniforms.name;
      }
     
      render() {
        const props = this.getFieldProps(undefined, {ensureValue: false});
        if (props.componentType === 'WYSIWYG') {
          return <MyTrumboWyg {...props} />
        }
     
        return <defaults.bootstrap4.AutoField {...this.props} />;
      }
    }
     
    const WYSIWYGComponent = {
      type: 'WYSIWYG Editor',
      schema: {
        type: String
      },
      sidebar: {
        icon: <i className="fa fa-file-text-o"/>,
        text: 'WYSIWYG Editor'
      },
    }
     
    <Easel
      AutoForm={defaults.bootstrap4.AutoForm}
      AutoField={CustomAuto}
      components={defaults.bootstrap4.components.concat([WYSIWYGComponent])}
    />

    Example: Text Area with admin configuration.

    Uniforms-bootstrap4 gives us a LongTextField, and that LongTextField can take rows as a prop. We'd like to show that in the admin section of the field in Easel.

    This example will just show the component configuration, since this already exists in defaults.bootstrap4

    import LongTextField from 'uniforms-bootstrap4/LongTextField';
     
    const LongTextFieldComponent = {
                                     type: 'Textarea',
                                     schema: {
                                       String,
                                       uniforms: {
                                         rows: 10                                     
                                       }
                                     },
                                     sidebar: {
                                       icon: <i className="fa fa-pencil-square-o" />,
                                       text: 'Textarea'
                                     },
                                     admin: {
                                       schema: new SimpleSchema({
                                         rows: {
                                           type: Number
                                         },
                                       })
                                     }
                                   }

    Install

    npm i react-easel

    DownloadsWeekly Downloads

    6

    Version

    0.0.14

    License

    MIT

    Last publish

    Collaborators

    • noahprince22