区分 material-ui SelectFields 并获取它们的值

Telling the difference between material-ui SelectFields and getting their values

我有一个动态生成输入的表单,其中一个输入是具有多个选项的 material-ui TextField 和 SelectField。不过,我在区分 select 字段时遇到了问题。在一个理想的世界中,我希望能够从这两个输入中收集数据并将它们存储为一个对象(即 {name: Employee, type_id: 1}),该对象将成为一个对象数组,具体取决于生成的输入数量。

我当前的代码如下所示:

import React from 'react';
import TextField from 'material-ui/TextField';
import RaisedButton from 'material-ui/RaisedButton';
import SelectField from 'material-ui/SelectField';
import MenuItem from 'material-ui/MenuItem';
import DatatypeStore from '../../stores/DatatypeStore';

const styles = {
    customWidth: {
        width: 100,
    },
};

class MultipleEntry extends React.Component {

    state={inputs: [], columnHeaders: [], value: 1};

    addInputField(e) {
        e.preventDefault();

        let inputs = this.state.inputs;
        inputs.push({name: null});
        this.setState({inputs});
    }

    handleChange(e, index, value) {
        const isSelectField = value !== undefined;

        if (isSelectField) {
            console.log(index, value);
        } else {
            console.log(e.target.value);
        }
    }

    render() {

        let {inputs, columnHeaders, value} = this.state;

        return (
            <div className="col-md-12">
                {inputs.map((input, index) => {
                    let name = "header " + index;
                    return (
                        <div key={index}>
                            <br />
                            <TextField
                                hintText="Enter the name for the column"
                                floatingLabelText="Column Name"
                                type="text"
                                name={name}
                                onChange={e => this.handleChange(e)} 
                            />
                            <SelectField
                                value={this.state.value}
                                onChange={e => this.handleChange(e, index, value)}
                                style={styles.customWidth} 
                            >
                                {DatatypeStore.getDatatypes().map(el => {
                                    return <MenuItem key={el.id} value={el.id} primaryText={el.name} />;
                                })}
                            </SelectField>
                            <br />
                        </div>
                    );
                })}
                <br/>
                <RaisedButton
                    style={{marginTop: 50}} 
                    label="Add column input"
                    secondary={true} 
                    onClick={e => this.addInputField(e)}  
                />
                <br />
            </div>
        );
    }
}

export default MultipleEntry;

所以,是的,我将不胜感激做我想做的事的例子。如果你能用 material-ui 组件做到这一点就更好了!

感谢您的宝贵时间

更新

这里是父组件

import React from 'react';
import MultipleEntry from './MultipleEntry.jsx';
import Paper from 'material-ui/Paper';
import TextField from 'material-ui/TextField';
import RaisedButton from 'material-ui/RaisedButton';
import TokenStore from '../../stores/TokenStore';

const styles = {
    paper: {
        marginTop: 50,
        paddingBottom: 50,
        width: '100%',
        textAlign: 'center',
        display: 'inline-block',
    },
};

class ColumnHeaderForm extends React.Component {

    state = {title: '', input: null};

    changeValue(e) {
        const title = e.target.value;
        this.setState({
            title
        });
    }

    handleInputChange(columnHeaderArray) {
        let input = this.state.input;
        input = columnHeaderArray;
        this.setState({input});
    }

    handleFormSubmit(e) {
        e.preventDefault();

        let access_token = TokenStore.getToken();
        let title = this.state.title;
        let inputs = this.state.input;

        this.props.handleFormSubmit(access_token, title, inputs);
    }

    render() {

        let {title, input} = this.state;

        return (
            <div>
                <Paper style={styles.paper}>
                    <form role="form" autoComplete="off">
                        <div className="text-center">
                            <h2 style={{padding: 10}}>Fill out the column names (you can add as many as you need)</h2>
                            <div className="col-md-12">
                                <TextField
                                    hintText="Enter a title for the table"
                                    floatingLabelText="Title"
                                    type="text"
                                    onChange={e => this.changeValue(e)} 
                                />
                            </div>
                            <div className="col-md-12">
                                <MultipleEntry handleInputChange={this.handleInputChange.bind(this)} />
                            </div>
                            <RaisedButton 
                                style={{marginTop: 50}} 
                                label="Submit"
                                primary={true} 
                                onClick={e => this.handleFormSubmit(e)} 
                            />
                        </div>
                    </form>
                </Paper>
            </div>
        );
    }
}

export default ColumnHeaderForm;

根据我的理解,您希望以相同的方法处理 TextField 和 SelectField onChange。他们确实有不同的签名
文本字段(event, value)
选择字段(event, index, value)
但是您可以通过测试第三个参数轻松实现它,例如:

handleChange(event, index, value) {
    const isSelectField = value !== undefined;

    if(isSelectField) {
        // do whatever you need to do with the SelectField value
    } else {
        // do whatever you need to do with the TextField value
    }
}

注意: 你不应该改变你的状态,那是错误的。

let columnHeaders = this.state.columnHeaders;
columnHeaders[e.target.name] = e.target.value;

要避免它,您可以 "clone" 状态对象并在那里应用更改..

Object.assign({}, this.state.columnHeaders, {
    [e.target.name]: event.target.value
})

在此处阅读有关 Object.assign 的更多信息:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

---------------------------------------- ------------
更新示例 26/04/2016
现在您可以看到我只是更改 SelectField 的输入对象(我通过其 ID 找到的)中的 typeId。 TextField 几乎相同 - 只需更改字段名称..

handleChange(inputId, event, index, value) {
    const isSelectField = value !== undefined;

    if(isSelectField) {
        this.setState({
            inputs: this.state.inputs.map((input) => {
                return input.id === inputId ? Object.assign({}, input, {
                    typeId: value
                }) : input
            })
        })
    } else {
        this.setState({
            inputs: this.state.inputs.map((input) => {
                return input.id === inputId ? Object.assign({}, input, {
                    name: event.target.value
                }) : input
            })
        })
    }
}

//Make sure the id is unique for each input
addInputField(e) {
    e.preventDefault();

    this.setState({
        inputs: this.state.inputs.concat({ id: 1, name: null })
    });
}

//Binding the ID in the call so we can use it in that method..
<SelectField
    value={input.typeId}
    onChange={this.handleChange.bind(this, input.id)}
    style={styles.customWidth} 
>