代码之家  ›  专栏  ›  技术社区  ›  lem.mallari

在ReactJS中实现动态表单

  •  0
  • lem.mallari  · 技术社区  · 6 年前

    DynamicRequestorDetails ,获取要添加到其中的可能组件的列表(例如文本框或下拉列表)。这一个可以工作,并生成文本框/下拉列表。我的问题是 handleChange 父容器的事件似乎没有传递给组件处理程序生成的动态组件。我还有什么遗漏吗?我看到正确地传递了这些值,但是在调试期间 手摇 动态创建的组件未触发事件。

    我有以下文件:

    下拉组件:

    import React, {PropTypes} from 'react';
    
    const Dropwdown = ({identifier, value, selectChanged, options, label}) => {    
        return (
            <div className="row eis-field-row">
                <label className="col-xs-4 TheSansBold">{label}</label>
                <select className="col-xs-6"
                    name={identifier}
                    id={identifier}
                    onChange={selectChanged}
                    value={value}
                >
                    <option value="">--Please select one--</option>
                    {
                    options.map((option) => {
                        return <option key={option.Value} value={option.Value}>{option.Text}</option>;
                    })
                }                
                </select>
            </div>
        );
    };
    
    Dropwdown.propTypes = {
        identifier: PropTypes.string,
        defaultOption: PropTypes.object,
        value: PropTypes.string,
        selectChanged: PropTypes.func,
        options: PropTypes.arrayOf(PropTypes.object),
        label: PropTypes.string
    
    };
    
    export default Dropwdown;
    

    组件处理程序:

    import React from 'react';
    
    /* import components here */
    import Textbox from '../components/common/forms/Textbox';
    import Dropdown from '../components/common/forms/Dropdown';
    
    /* import component types */
    import * as types from '../constants/FieldTypes';
    
    export function getFieldValue(fieldValues, identifier) {
        let selectedItem = fieldValues.find(x => x.FieldID == identifier);
        if(Object.keys(selectedItem).length > 0) {
            return selectedItem.Value;
        }    
    }
    
    export function RenderComponent(field, handleChange, value) {
        switch(field.Type) {
            case types.TextComponent: {           
                return (
                    <Textbox
                        type="text"
                        label={field.Label}
                        id={field.Identifier}
                        name={field.Identifier}
                        value={value}
                        onChange={handleChange}
                        placeholder={field.Placeholder}
                        key={field.Identifier}
                    />
                );
            }
    
            case types.SelectComponent: {
                return (
                    <Dropdown
                        name={field.Identifier}
                        label={field.Label}
                        id={field.Identifier}
                        onChange={handleChange}
                        value={value}
                        options={field.Options}
                        key={field.Identifier}
                    />
                );
            }
    
            default: {
                return null;
            }
        }
    }
    

    dynamiccrequestordetails组件:

    import React, {PropTypes} from 'react';
    import * as ch from '../../utilites/componentHandler';
    
    const DynamicRequestorDetails = ({userinfo, ccValue, handleChange, isVisible, customFields, fieldValues}) => {
        let wrapperClass = " hidden";
        if(!isVisible) {
            wrapperClass = "";
        } else {
            wrapperClass = " hidden";
        }
    
        return (
            <div>
                <label className="label-headers TheSansBold">REQUESTOR DETAILS</label>
                <div className="row eis-field-row">
                    <label className="TheSansBold col-xs-4">Name</label>
                    <label id="requestorName" className="col-xs-6 field-value">{userinfo.DisplayName}</label>
                </div>
                <div className="row eis-field-row">
                    <label className="col-xs-4 TheSansBold ">Employee No</label>
                    <label className="col-xs-6 field-value">{userinfo.LanId}</label>
                </div>
                <div className="row eis-field-row">
                    <label className="col-xs-4 TheSansBold">Department</label>
                    <label className="col-xs-6 field-value">{userinfo.Department}</label>
                </div>
                <div className="row eis-field-row">
                    <label className="col-xs-4 TheSansBold">Designation</label>
                    <label className="col-xs-6 field-value">{userinfo.Title}</label>
                </div>
                <div className="row eis-field-row">
                    <label className="col-xs-4 TheSansBold">Contact No</label>
                    <label className="col-xs-6 field-value">{userinfo.Mobile}</label>
                </div>
                <div id="reqDivsion" className={"row eis-field-row" + wrapperClass}>
                    <label className="col-xs-4 TheSansBold">Divsion</label>
                    <select className="col-xs-6" onChange={handleChange}>
                        <option value="1">--Select Division--</option>
                        <option value="2">Group 1</option>
                        <option value="3">Group 2</option>
                        <option value="4">Group 3</option>
                        <option value="5">Group 4</option>
                        <option value="6">Group 5</option>
                        <option value="7">Group 6</option>
                    </select>
                </div>            
                <div className={"row eis-field-row" + wrapperClass}>
                    <label className="col-xs-4 TheSansBold">Cost Center: </label>
                    <input type="text" value={ccValue} onChange={handleChange} className="col-xs-6" />
                </div>
                {
                    customFields.map(customField => {
                        let fieldValue = ch.getFieldValue(fieldValues, customField.Identifier);
                        return ch.RenderComponent(customField, handleChange, fieldValue);
                    })
                }            
            </div>
        );
    };
    
    DynamicRequestorDetails.propTypes = {
        userinfo: PropTypes.object.isRequired,
        ccValue: PropTypes.string,
        handleChange: PropTypes.func,
        divChange: PropTypes.func,
        isVisible: PropTypes.bool,
        customFields: PropTypes.arrayOf(PropTypes.object),
        fieldValues: PropTypes.arrayOf(PropTypes.object)
    };
    
    export default DynamicRequestorDetails;
    

    父组件:

    const steps = def.ProcessPages[0].Steps;
    
    class NewSMILEPage extends React.Component {
        constructor(props, context) {
            super(props, context);
    
            this.state = {
                FieldValues: []
            };
    
            this.handleChange = this.handleChange.bind(this);
            this.goBack = this.goBack.bind(this);
        }
    
        componentDidMount() {
            this.populateFieldValues();
        }
    
        componentWillReceiveProps(newProps) {
            if(newProps.smile.FieldValues != this.props.smile.FieldValues) {
                this.setState({FieldValues: newProps.smile.FieldValues});
            }
        }
    
        handleChange(e, identifier) {
    
        }
    
        populateFieldValues() {
            //populates values for my state
        }
    
        updateFieldValues(fv) {
            //updates values for my state
        }
    
        goBack() {
            //do some action
        }    
    
        render() {
            if(this.state.FieldValues.length > 0) {
                return (
                    <div className="container-fluid">
                        <div className="row">
                            <div className="col-xs-4">
                                <FormHeader formName={this.props.eforms.SelectedEForm.Title} />
                            </div>
                            <div className="col-xs-8">
                                <StepTracker steps={def.ProcessPages[0].Steps} />
                            </div>
                        </div>
                        {/*Step Name and Image*/}
                        <div className="row form-label-container">
                            <img src={HeaderImage} alt="Header Image" width="40" className="pull-left"/>
                            <p className="form-header pull-left TheSansBold">NEW REQUEST</p>
                        </div>
                        <div className="row">
                            <div className="col-xs-6 pull-left">
                                <DynamicRequestorDetails
                                    userinfo={this.props.userinfo}
                                    isVisible={this.props.isVisible} 
                                    ccValue=""
                                    ccValueChange={this.handleChange}
                                    divChange={this.divisionChange}
                                    customFields={def.ProcessPages[0].Fields}
                                    handleChange={this.handleChange}
                                    fieldValues={this.state.FieldValues}
                                />
                            </div>
                        </div>
                        <div className="row footer-button-container footer">
                            <div className="pull-left">
                                <button id="btnBack" type="button" className="btn btn-back" onClick={this.goBack} >CANCEL</button>
                            </div>
                            <div className="pull-right">
                                <button id="btnNext" type="button" className="btn btn-next margin-right-lg" onClick={this.goNext}>NEXT</button>
                            </div>
                        </div>
                    </div> 
                );
            } else {
                return (<h1>Loading</h1>);
            }
        }
    }
    
    function mapStateToProps(state, ownProps) {
        return {
            //state to props returned here      
        };
    }
    
    function mapDispatchToProps(dispatch) {
        return {
            //actions returned here
        };
    }
    
    NewSMILEPage.propTypes = {
        //prop checking done here
    };
    
    export default connect(mapStateToProps, mapDispatchToProps)(NewSMILEPage);
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   xadm    6 年前

    参数名不匹配selectChanged/handleChange,缺少 selectChanged ...

    你在用 onChange 在组件上 RenderComponent 一旦改变 应仅在呈现“普通”html元素时使用。