How to dynamically build a redux form?

只愿长相守 提交于 2019-11-30 15:45:11

I am following this approach for building a form dynamically. I am just declaring metadata of form fields (type, placeholder, the unique name of each field, etc.) like this:

const fields = [
      { name: 'name', type: 'text', placeholder: 'Enter Name' },
      { name: 'age', type: 'number', placeholder: 'Enter age' },
      { name: 'email', type: 'email', placeholder: 'Enter Email' },
      { name: 'employed', type: 'checkbox' },
      {
        name: 'favouriteColors',
        type: 'select',
        options: [
          { label: 'Red', value: 'red' },
          { label: 'Yellow', value: 'yellow' },
          { label: 'Green', value: 'green' },
        ],
      },
    ]

Now, I am just iterating over these fields and rendering input for each field like the way I have done in renderField component given below. My general form component looks like this:

import React from 'react'
import { Field, reduxForm } from 'redux-form/immutable'

const renderField = ({ input, field }) => {
  const { type, placeholder } = field
  if (type === 'text' || type === 'email' || type === 'number' || type === 'checkbox') {
    return <input {...input} placeholder={placeholder} type={type} />
  } else if (type === 'select') {
    const { options } = field
    return (
      <select name={field.name} onChange={input.onChange}>
        {options.map((option, index) => {
          return <option key={index} value={option.value}>{option.label}</option>
        })}
      </select>
    )
  } else {
    return <div>Type not supported.</div>
  }
}

const SimpleForm = ({ handleSubmit, fields }) => {
  return (
    <div>
      {fields.map(field => (
        <div key={field.name}>
          <Field
            name={field.name}
            component={renderField}
            field={field}
            />
        </div>
      ))}
      <div onClick={handleSubmit}>Submit</div>
    </div>
  )
}

export default reduxForm({
  form: 'simpleForm'
})(SimpleForm)

and passing fields to SimpleForm component like this:

<SimpleForm fields={fields} onSubmit={() =>{}}/>

Now it's your choice that you want to fetch fields like this from the server or just want to fetch only items and make fields like this (by passing item as the name of field) on the frontend.

By using this approach, I am able to re-use template based on given type.

If someone has a better approach to make a form dynamically, then I would love to learn that too.

Edit: If we have to pass form name dynamically, then a small change will be required:

export default reduxForm({})(SimpleForm)

and we can pass form name while this component like this:

<SimpleForm form={'simpleForm'} fields={fields} onSubmit={() =>{}} />

you can create a component form and use it in a .map() function and pass formName as props like this...

render() {
 return(
   <div>
     {yourDataFromServer.map((item, index) => 
      <ReduxFormComp
        form={`${FORM_NAMES.SIMPLE_FORM}__${index}`}
        initialValues={item}
      />
    )}
   </div>
);
}

NOTE: when you use from initialValues for init your form, all field name should equal to your data.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!