• Demo address: kerrycodes.github. IO /
  • Github:github.com/KerryCodes/…
  • Installation:npm i leggo

story

Because of the departure of my old staff, I took over a publishing module consisting entirely of forms, without having read the business source code. Later rushing in to maintain the code as new requirements are added. Notice I used the quantifier “glop”, you know what I’m talking about. Because the whole module lacks the top-level design, resulting in high maintenance costs and frequent bugs. I started to wonder why I couldn’t just create and maintain these forms by dragging and dropping. So leggo was born. The name comes from Lego, which means to complete the form design like building blocks.

Leggo philosophy

  • Although “drag and drop” is the most intuitive and simple way to interact. But leggo isn’t for non-front-end people. Leggo is a productivity tool for professional front-end developers

  • Leggo was never intended to be a big, all-in-one form configuration solution. The first edition even took an afternoon to complete. So Leggo doesn’t sacrifice ease of use for form components that can implement complex logic. What Leggo is really about is helping front-end developers build and maintain form structures quickly, making it easy for them to reshuffle form components mindlessly. This enables front-end development to focus more on developing form components with specific complex logical interactions.

  • Leggo keeps the space almost completely open for free expansion. Not only drag-and-drop form component libraries can be freely registered. All components rendered by leggo templates can also be easily overwritten, assembled, or overridden as a whole. You can even expose various public states and functions for Leggo consumption. So LegGo isn’t limited to simple form design scenarios, it’s up to developers to be bold and expand.

  • The cost of getting started is extremely low. If you are familiar with React and Antd, you only need to learn one or two leggo apis to start deploying in your project. All properties and events of the Antd library Form, form.item, and related input components can still be defined and used normally.

The base application

Const Leggo = Leggoform.useleggo (schemaModel, Middleware, publicStates) is at the heart of all of the following code, hopefully not too much to read.

Assuming you’ve generated a form template with the Leggo form Designer (get a JSON object, schemaModel in the following code), you have the actual form you need with just two lines of code:

export const schemaModel= {
  //JSON
}
Copy the code
export { LeggoForm } from 'leggo'
export { schemaModel } form './schemaModel'


function MyForm(){
  const leggo= LeggoForm.useLeggo(schemaModel)
  
  return <LeggoForm leggo={leggo} />
}
Copy the code

LeggoForm is exported from Leggo, and schemaModel is JSON generated through the Leggo form designer. LeggoForm is a high-level component that parses the template JSON and renders it into the actual form component.

There is little difference in usage between LeggoForm and Antd forms (except that the leggo attribute must be mounted). You can define any properties allowed by the LeggoForm component and run them normally, like this:

function MyForm(){
  const leggo= LeggoForm.useLeggo(schemaModel)
  const [form]= Form.useForm()

  return (
    <LeggoForm leggo={leggo} 
      form={form} 
      labelCol={ span: 6 }
      wrapperCol={ span: 14 }
      onValuesChange={handleValuesChange} 
      onFinish={hanldeFinish} 
      .
      .
      .
    />)}Copy the code

Considering that your form template schemaModel may not exist locally but need to be pulled asynchronously and remotely from the server, you can deploy it like this:

function MyForm(){
  const leggo= LeggoForm.useLeggo()
  const [form]= Form.useForm()
  
  useEffect(() = > {
    leggo.resetSchemaModel(schemaModel)
  }, [schemaModel])

  return (
    <LeggoForm leggo={leggo} 
      form={form} 
      labelCol={ span: 6 }
      wrapperCol={ span: 14 }
      onValuesChange={handleValuesChange} 
      onFinish={hanldeFinish} 
      .
      .
      .
    />)}Copy the code

A simple form with the above code is sufficient to deploy the application. Let’s step into a more complex scenario. Here is one of the form components we need. Notice that there is a “synchronize” button on the right side of the component. There is no way to drag and drop the entire design of this personalized component.

Don’t worry, let’s finish the design of the classic form component on the left by dragging and dropping. The buttons on the right are only injected by middleware functions before rendering the form. Middleware functions are used in LegGo as a means of flexible extension before rendering the form. The code is as follows:

import { TConfigs } from 'leggo/lib/interface';


function MyForm(){
  const leggo= LeggoForm.useLeggo(schemaModel, middleware)
  const [form]= Form.useForm()
  
  // Async
  // useEffect(() => {
  // leggo.resetSchemaModel(schemaModel, middleware)
  // }, [schemaModel])

  return (
    <LeggoForm leggo={leggo} />)}// Define a middleware function
function middleware(configs: TConfigs) {
  configs.Successor= (props: React.PropsWithChildren<any>) = > (
    <div style={{display: 'flex'}} >
      { props.children }
      <Button>synchronous</Button>
    </div>)}Copy the code

It is worth noting that the middleware function is only executed during the entire schemaModel injection. No matter how the form is later updated and rendered, the intermediate function will not run (unless you re-inject a new schemaModel via Leggo.resetSchemamodel). So you don’t have to worry about performance issues that can be caused by middleware functions.

You’ll notice that the Leggo engine injects a parameter, configs, into the middleware function when it runs it. This object is very important. It comes from schemaModel, where almost all the parameters you drag and set through the Leggo form designer are stored. In fact, it is through middleware functions that we are adapting the schemaModel generated by the form designer. There are two key properties in configs: itemProps and inputProps.

itemProps

The parameters of itemProps include name, label, and rules. Yes, this object is injected directly into the form. Item component:

<Form.Item {... itemProps} ></Form.Item>

inputProps

Parameters for inputProps include disabled, style, placeholder, and htmlType. This object is injected directly into the input component:

<Input {... inputProps} />

<Checkbox.Group {... inputProps} />

<DatePicker {... inputProps} />

Then you find that you have ample opportunity to extend the design of the form through middleware functions before rendering it, such as:

function middleware(configs: TConfigs) {
  const { itemProps, inputprops }= configs
  
  if(itemProps.name ! = ='test') {return } // Filter the forms we need to change
  
  itemProps.label= 'test2' // We have replaced the label
  
  itemProps.options= [ // We replaced the options data required by the options class component
    {label: 'zhejiang'.value: 'zj'},
    {label: 'fujian'.value: 'fj'},
  ]
  
  configs.Successor= (props: React.PropsWithChildren<any>) = > (
    <div style={{display: 'flex'}} >
      { props.children }
      <Button>synchronous</Button> 
    </div>
  ) // We added a button on the right side of the form
  
  configs.SuperSuccessor= () = > (
    <Form.Item label="newOne" name="newOne">
      <Input />
    </Form.Item>
  ) // We even completely overwrite and discard the original form component with a new form component
}
Copy the code

Successor and SuperSuccessor

Succeeded and supersucceeded are very useful for complex forms and are the key for developers to focus on the components of complex logical forms with Leggo. The so-called placeholder form component in leggo form designer reserves structural space for the replacements of the forerunners and superforerunners.

The difference is that the original form components are only modifications to it (the original form components are passed to it by children, itemProps and inputprops are still injected). The supersucceeded was very aggressive in overwriting and ditching the original form components (itemProps and inputprops were also ditched).

<Form.Item {... itemProps}><Successor>
    <Input {. inputprops} / >
  </Successor>
</Form.Item> 
Copy the code
<SuperSuccessor />
Copy the code

The above is a one-time transformation of schemaModel with middleware functions. If you need to change the rendering of the form at any time, such as the disabled property, you can do so at any time by calling Leggo.updateschema. Each form component is individually rerendered, so you don’t have to worry about performance either. As follows:

// Can be called at any time
leggo.updateSchema('select'.configs= > {
  const { inputprops }= configs
  inputprops.disabled= true
})


// How middleware functions are implemented (note that this function is only run once!) :
function middleware(configs: TConfigs) {
  const { itemProps, inputprops }= configs
  if(itemProps.name === 'select'){ 
    inputprops.disabled= true}}Copy the code

Advanced application

Ok, let’s move on to a more complex design scenario. Suppose we need to design a form that allows data linkage, and whether the date component is mandatory depends on the value of the radio component.

All we need to do is set up data associations and simple logical operations through the Leggo form designer.

[{label: 'will choose the date, the value: 1}, {label:' not will choose date, value: 2}]

If our associated value is available at runtime, we can simply pass in a common state before the form is actually rendered. The common state can be either a value or a function, and the LEGgo engine recognizes it automatically.

Another common scenario is that components such as Select or Radio need to pull options data remotely. Leggo can also be very convenient to achieve such requirements.

Data with associated buttons can be set to associated data

The public state is introduced as follows:

const publicStates= {
  testvalue: 1084.testFunc: () = > 'test',}function MyForm(){
  const leggo= LeggoForm.useLeggo(schemaModel, middleware, publicStates)
  const [form]= Form.useForm()

  return (
    <LeggoForm leggo={leggo} />)}Copy the code

Leggo form designer

Demo address: kerrycodes.github. IO /

If you need to deploy the form designer directly in your project, you can introduce the LeggoConfigs component directly, and the onGetSchemaModel property will be injected and executed automatically after schemaModel is generated. As follows:

<LeggoConfigs onGetSchemaModel={postSchemaModelData} />

function postSchemaModelData= (schemaModel: TSchemaModel) = >{
  console.log('Send schema~~~~~~', schemaModel)
}
Copy the code

Important!

Project address: github.com/KerryCodes/…

I have been in the industry for almost a year, and I have accumulated 20 fans without Posting any answers, but Github’s star still hangs 0!! Can you move the golden finger, let me experience the pleasure of star ~