如何根据Redux表单中的另一个输入有条件地显示输入?

时间:2016-06-02 12:04:18

标签: reactjs redux react-redux redux-form

如果下拉值为others,则需要新文本字段,但必须更改变量,因为building_type在新文本字段中放置others值。在这种情况下,在哪里以及如何使两个变量相等?

import React from 'react'
import { connect } from 'react-redux'
import { reduxForm } from 'redux-form'
import { StandardForm, TextField, UsStatesSelectField, SelectField } from './../forms'
import { loadProperty, saveProperty } from './../../models/properties'

const validate = values => {
    const required = value => value ? null : 'Required'
    const errors = {}
    errors.name = required(values.name)
    errors.street_address = required(values.street_address)
    errors.city = required(values.city)
    errors.state = required(values.state)
    errors.zip = required(values.zip)
    errors.building_type = required(values.building_type)

    return errors
}

const PropertyInfoForm = reduxForm({
    form: 'propertyInfo',
    fields: ['name', 'street_address', 'city', 'state', 'zip', 'building_type', 'building_other_type'],
    validate
})(React.createClass({
    render() {
        return (
            <StandardForm {...this.props} title="Property Info" resetButton="Reset">
                <TextField {...this.props.fields.name} label="Property Name" />
                <TextField {...this.props.fields.street_address} label="Property    Address" />
                <div className="three fields">
                    <TextField {...this.props.fields.city} label="City" />
                    <UsStatesSelectField {...this.props.fields.state} label="State" />
                    <TextField {...this.props.fields.zip} label="Zip Code" />
                </div>
                <SelectField {...this.props.fields.building_type}
                    label="Please select a Building Type for the junctionbox"
                    options={[
                        ['office', 'Office'],
                        ['private_home', 'Private Home'],
                        ['residential', 'Residential'],
                        ['retail', 'Retail'],
                        ['restaurant', 'Restaurant'],
                        ['school', 'School'],
                        ['townhouse', 'Townhouse'],
                        ['warehouse', 'Warehouse'],
                        ['other', 'Other']
                    ]}
                />
                {((this.props.fields.building_type.value) === 'other') ? (
                    <TextField {...this.props.fields.building_other_type} label="Please Specify Other Building Type" />
                ) : ''}
            </StandardForm>
        )
    }
}))

export default connect(
    (state, ownProps) => ({
        property: state.entities.property[ownProps.params.propertyId]
    }),
    dispatch => ({
        dispatch
    })
)(({ dispatch, property }) => (
    <PropertyInfoForm
        initialValues={property}
        onSubmit={(values) => dispatch(saveProperty(property.id, values)).then(_ => dispatch(loadProperty(property.id)))}
    />
))

1 个答案:

答案 0 :(得分:0)

您可以使用formValueSelector

它可用于从connect的{​​{3}}函数内部的状态访问表单字段值,以便将该值作为prop传递给表单组件。

将forms字段值作为prop允许进行各种与值相关的事情。

1。 (小)条件Field示例

// SomeForm.jsx:

import React from 'react';
import {connect} from 'react-redux';
import {Field, reduxForm, formValueSelector} from 'redux-form';

let SomeComponentUseFirstFieldValue = ({firstFieldValue, ...props}) => {
    // do something with 'firstFieldValue'
    return (...);
}

const mapStateToPropsForSomeComponentUseFirstFieldValue = (state, initalProps) => {
    // Use 'initalProps.firstFieldValue' to retrieve something from state if needed.

    return {...};
}

const mapDispatchToPropsForSomeComponentUseFirstFieldValue = (dispatch, ownProps) => {
    // Use 'ownProps.firstFieldValue' to retrieve with dispatch
}

SomeComponentUseFirstFieldValue = connect(
    mapStateToPropsForSomeComponentUseFirstFieldValue, 
    mapDispatchToPropsForSomeComponentUseFirstFieldValue
)(SomeComponentUseFirstFieldValue);

let SomeForm = ({handleSubmit, firstFieldValue, ...props}) => (
    <form onSubmit={handleSubmit}>
        <Field 
            name='first'
            component='input'
            type='text'
        />
        <Field
            name='second'
            component={SomeComponentUseFirstFieldValue}
            firstFieldValue={firstFieldValue} // Pass 'firstFieldValue' to Field component.
        />
        {firstFieldValue && 
            <Field 
                ... // Conditional show Field.
            />
        } 
    </form>
);

SomeForm = reduxForm({
    // options
})(SomeForm);

const mapStateToPropsForSomeForm = (state, initialProps) => ({
    firstFieldValue: (formValueSelector(initialProps.name))(state, 'first')
});

SomeForm = connect(
    mapStateToPropsForSomeForm
)(SomeForm);

export default SomeForm;

// AnotherComponent.jsx:

import React from 'react';
import SomeForm from 'SomeForm';

const AnotherComponent = (props) => (
    <SomeForm
        name='form1'
        initialValues={...}
        ...
    />
)

2。解决问题

import React from 'react';
import {connect} from 'react-redux';
import {reduxForm} from 'redux-form';
import {StandardForm, TextField, UsStatesSelectField, SelectField} from './../forms';
import {loadProperty, saveProperty} from './../../models/properties'

const validate = values => {
    const required = value => value ? null : 'Required'
    const errors = {}
    errors.name = required(values.name)
    errors.street_address = required(values.street_address)
    errors.city = required(values.city)
    errors.state = required(values.state)
    errors.zip = required(values.zip)
    errors.building_type = required(values.building_type)

    return errors
}

let PropertyInfoForm = (props) => (
    <StandardForm {...props} title="Property Info" resetButton="Reset">
        <TextField {...props.fields.name} label="Property Name" />
        <TextField {...props.fields.street_address} label="Property    Address" />
        <div className="three fields">
            <TextField {...props.fields.city} label="City" />
            <UsStatesSelectField {...props.fields.state} label="State" />
            <TextField {...props.fields.zip} label="Zip Code" />
        </div>
        <SelectField {...props.fields.building_type}
            label="Please select a Building Type for the junctionbox"
            options={[
                ['office', 'Office'],
                ['private_home', 'Private Home'],
                ['residential', 'Residential'],
                ['retail', 'Retail'],
                ['restaurant', 'Restaurant'],
                ['school', 'School'],
                ['townhouse', 'Townhouse'],
                ['warehouse', 'Warehouse'],
                ['other', 'Other']
            ]}
        />
        {(props.buildingTypeValue === 'other') ? (
            <TextField {...props.fields.building_other_type} label="Please Specify Other Building Type" />
        ) : ''}
    </StandardForm>
)

PropertyInfoForm = reduxForm({
    form: 'propertyInfo',
    validate: validate,
    fields: [
        'name', 
        'street_address', 
        'city', 'state', 
        'zip', 
        'building_type', 
        'building_other_type'
        ],
})(PropertyInfoForm);

const mapStateToProps = (state, initialProps) => ({
    property: state.entities.property[initialProps.params.propertyId],
    buildingTypeValue: (formValueSelector(initialProps.name))(state, 'building_type')
});

const mapDispatchToProps = dispatch => ({
    dispatch // Mhh... Passing 'dispatch' directly to props smells bad...
});

PropertyInfoForm = ({dispatch, property, buildingTypeValue}) => (
    <PropertyInfoForm
        initialValues={property}
        onSubmit={
            values => dispatch(
                saveProperty(property.id, values)).then(_ => dispatch(loadProperty(property.id))
            )
        }
        buildingTypeValue={buildingTypeValue}
    />
);

PropertyInfoForm = connect(
    mapStateToProps,
    mapDispatchToProps
)(PropertyInfoForm);

export default PropertyInfoForm;