FormSection

The FormSection component makes it easy to split forms into smaller components that are resuable across multiple forms. It does this by prefixing the name of Field, Fields and FieldArray children, at any depth, with the value specified in the name prop.

Props you can pass to FormSection

name : String [required]

The name all child fields should be prefixed with.

component : String | Component [optional]

If you give FormSection more than one child element, it will be forced to create a component to wrap them with. You can specify what type of component you would like it to be (div, section, span). Defaults to 'div'.

Note that any additional props (e.g. 'className', 'style') that you pass to FormSection will be passed along to the wrapper component.

Example usage

An example use case for FormSection is an order form where it's possible to have enter the details of a buyer and a separate recipient. The fields for both buyer and recipient are the same and it therefore makes sense to split this section into a component called Party. Now a Party for exampe consists of a fields like givenName, middleName, surname and address so again it makes sense to split the address section into it's own reusable component called Address.

The above description results in the following code:


//Address.js
class Address extends Component {
    render() {
        return <div>
            <Field name="streetName" component="input" type="text"/>
            <Field name="number" component="input" type="text"/>
            <Field name="zipCode" component="input" type="text"/> 
        </div>
    }
}

//Party.js
class Party extends Component {
    render() {
        return <div>
            <Field name="givenName" component="input" type="text"/>
            <Field name="middleName" component="input" type="text"/>
            <Field name="surname" component="input" type="text"/>
            <FormSection name="address">
                <Address/>
            </FormSection>
        </div>
    }
}

//OrderForm.js
class OrderForm extends Component {
    render() {
        return <form onsubmit={...}>
            <FormSection name="buyer">
                <Party/>
            </FormSection>
            <FormSection name="recipient">
                <Party/>
            </FormSection>
        </form>
    }
}
//don't forget to connect OrderForm with reduxForm()

The full names of the fields in the above example will end up looking something like buyer.address.streetName which in turn results in the following result structure:


{
    buyer: {
        givenName: "xxx",
        middleName: "yyy",
        surname: "zzz",
        address: {
            streetName: undefined,
            number: "123",
            zipCode: "9090"
        }
    },
    recipient: {
        givenName: "aaa",
        middleName: "bbb",
        surname: "ccc",
        address: {
            streetName: "foo",
            number: "4123",
            zipCode: "78320"
        }
    }
}

For component such as Address that rarely change form section name it can be benificial to make the component inherit from FormSection instead of Component and set a default name prop as seen below:


class Address extends FormSection {
    //ES2015 syntax with babel transform-class-properties
    static defaultProps = {
        name: "address"
    }
    render() {
        return <div>
            <Field name="streetName" component="input" type="text"/>
            <Field name="number" component="input" type="text"/>
            <Field name="zipCode" component="input" type="text"/> 
        </div>
    }
}
//Regular syntax:
/*
Address.defaultProps = {
    name: "address"
}
*/