/form

React JsonSchema drived dynamic form engine. Support theme (antd...) assign

Primary LanguageJavaScriptOtherNOASSERTION

Table of Contents


Details & Demo by visite official site https://ver01.com

Start

Ver01Form is standalone lib for render JsonSchem to React Form,with different react themes supports.

Online Demo

CodeSandbox Demo

Schema Playground

local Demo

git clone git@github.com:ver01/form.git

npm install

npm run start

visit http://localhost:8888 for schema demo

Initialize

import npm package

  • Core npm package is @ver01/form.

  • Most of times you need using it with theme (eg: @ver01/form-theme-antd). Or you can define theme by yourself.

Uncontrolled Mode

  • With defaultValue props
<Ver01Form
    schema={{
        title: "Uncontrolled Mode:",
        type: "string"
    }}
    defaultValue="hello World"
    onChange={this.onChange.bind(this)}
/>

Live Demo

Controlled Mode

  • with defaultValue props
<Ver01Form
    schema={{
        title: "Controlled Mode:",
        type: "string"
    }}
    value={this.state.value}
    onChange={this.onChange.bind(this)}
/>

Live Demo

Theme

Now antd theme avaliavle now, others will come soon.

issue you wanted most react theme~~ (1 theme in at most 1 week)

Requirement

  • @ver01/form is standalone lib. No other package needed
  • But, you need import form theme package. Which may involve other react component framework (most of time includes in your project already).

Theme

Official theme

Custom theme

Component Schema

We assigned a json like schema to define react componet.

The entry file like this.

Theme entry file should export structure like this:

// Export Theme
export default {
    validators: {
        // buildin just need msgBuilder
        minLength: ({ value, ruleValue, schema }) => ({
            errorType: "feedbackStr",
            errorData: `should NOT be shorter than ${ruleValue} characters`,
        }),
        ...
        // custom need checkLogic
        otherCustomValidLogic
    },
    components: {
        // 5base type
        string: {
            getWidget: [({ schema }) => ({
                widgetName: "readonly",
                widgetData: { text: "True"},
            })], // special widget pick logic: return { widgetName, widgetData }
            widgets: {
                select: {
                    formatter: val => (val ? "true" : "false"), // format value to componet
                    normalizer: val => (val === "true" ? true : false), // format value to output
                    component: FormItem, // react component
            		    propsMixinList: ["style"], // user defined in JsonSchema $vf extend config
                    props: formItemProps, // component props defined in other place
                    children: [ // component children (recursion)
                        {
                            component: Select, 
            				propsMixinList: ["placeholder"],
                            props: { // props can dynamic generate with $vf_ prefix; more detail see [Dynamic props generator rule] section below
                                $vf_value: ({ value }) => value,
                                $vf_onChange: ({ handle }) => handle.onChange
                            }
                        }
                    ]
                },
                radio: radioWidget // defined as select widget
            }, // widget define: { [widgetName]: WidgetComponentSchema }
            errorObjGenerator:({ errors }) => {
                const errorMessage = [];
                errors.map(error => {
                    const { errorType, errorData } = error;
                    switch (errorType) {
                        default:
                            errorMessage.push(errorData);
                            break;
                    }
                });
                // return as errorObj
                return errorMessage.length
                    ? {
                    message: (
                        <ul>
                            {errorMessage.map((it, ind) => (
                                <li key={ind}>{it}</li>
                            ))}
                        </ul>
                    ),
                }
                : null;
            }, // generator errorObj for WidgetComponentSchema render widget
        },
        number,
        integer,
        boolean,
        null,
        // 1root only(for body holder)
        root,
        // 1control only(for control schema oneof anyof allof)
        control,
        // 2container
        array,
        object,
    },
};

Dynamic props generator rule

for props
 {
    isRoot: true,

    rootValue: {},
    rootSchema: {},

    parentSchema: {},

    value: {},
    schema: {},

    objectKey: "a",
    arrayIndex: 3,

    handle: {
        onChange: () => {},
        // for array
        canMoveUp: false,
        canMoveDown: false,
        canAppend: false,
        canRemove: false,
        moveUp: () => {},
        moveDown: () => {},
        append: () => {},
        remove: () => {},
        // for control
        hasSchemaControl: true, // child formnode has SchemaList
        schemaList: [{ schema: {}, valid: true, selected: true }], // no control is null
        schemaSelect: ind => {
            /* aform func */
        },
    },

    schemaOption: {
        // read by schema.$vf_opt.option
        // for array:
        orderable: true,
        removable: true,
        appendable: true,
        // for string:
        disabled: false,
        readonly: false,
        fileHandle: () => {}, // ?
        // for object:
        order: ["key_a", "key_b"],
    },

    formProps: {
        validators: {},
    },

    formOption: {},

    errorObj: {
        // custom
    },
};
for WidgetComponentSchema
{
    formatter: () => {},
    normalizer: () => {},
}

Value

Value In

Uncontrolled Mode
  • You need set the defaultValue props
  • unset defaultValue & value props also caused ver01Form in Uncontrolled Mode
  • The Form will use the defaultValue in first defined, deal with some situation defaultValue set async
// uncontrolled Mode:
<Ver01Form
  schema={{ type: 'string'}}
  defaultValue='helloWorld'
  onChange={console.info}
/>
Controlled Mode
  • You need set the value props.
  • onChange will trigger new value, but form will change when value changed.
// Controlled Mode:
<Ver01Form
  schema={{ type: 'string'}}
  value={this.state.value}
  onChange={value=>this.setValue({value})}
/>

Value Out

We not export some value post method, you can get value by onChange event, then deal with it as you wish

render(){
return <div>
  <Ver01Form
    schema={{ type: 'string'}}
    value={this.state.value}
    onChange={value=>this.setValue({value})}
  />
  <Button onClick={()=>{postServer(this.state.value)}}>Submit</Button>
</div>
}

Validate

validate result will export by onValidate method

when validate failed, error set as:

  • validateErrValuePath: the path which part valued valid failed.
  • errorObj: Generate by [Component Schema](#Component Schema) errorObjGenerator function.
  • errors: Generate by [Component Schema](#Component Schema) validators function
    • return as array
    • [{ errorType: "errorTypeString", errorData: AnyType }]
render(){
return <div>
  <Ver01Form
    schema={{
      "type": "object",
      "required": [
          "firstName",
      ],
      "properties": {
          "firstName": {
              "type": "string"
          }
      }
    }}
    value={{ firstName: '' }} // zero length string cause required check
    onValidate={error=>this.setState({errors: error && error.errors})} // error : { [validateErrValuePath]: {errorObj, errors} }
  />
  <Button onClick={()=>{
    if (this.state.errors){
      postServer(this.state.value);
    }else {
      console.info(this.state.errors);
    }
  }>Submit</Button>
</div>
}

JSON Schema Support

$vf_opt

we extended JSON Schema By $vf_opt section

$vf_opt.props

will mixin to all components belone to one value node. Filtered by [Component Schema](#Component Schema) propsMixinList

$vf_opt.widget

string, assign the component used. Defined in [Component Schema](#Component Schema) widgets

$vf_opt.option
  • For array
    • orderable(default true)
    • addable(default true)
    • removeable(default true)
  • For string
    • disabled
    • readonly
  • For object
    • order: ['first-key', 'second-key', '*', 'last-key']
$vf_opt.validate

[ruleName]: ruleValue

see sample-validation [local demo](#local demo)

Validate can be defined in formProps or buildin validate