如何从material-ui TextField,DropDownMenu组件获取数据?


71

我创建表单,我包括几个TextField,DropDownMenu材质UI组件,问题是如何从一个obj中的所有TextField,DropDownMenus收集所有数据并将其发送到服务器。对于TextField,它具有TextField.getValue()返回输入的值。但是我不知道如何使用它。

var React = require('react'),
    mui = require('material-ui'),
    Paper = mui.Paper,
    Toolbar = mui.Toolbar,
    ToolbarGroup = mui.ToolbarGroup,
    DropDownMenu = mui.DropDownMenu,
    TextField = mui.TextField,
    FlatButton = mui.FlatButton,
    Snackbar = mui.Snackbar;

var menuItemsIwant = [
  { payload: '1', text: '[Select a finacial purpose]' },
  { payload: '2', text: 'Every Night' },
  { payload: '3', text: 'Weeknights' },
  { payload: '4', text: 'Weekends' },
  { payload: '5', text: 'Weekly' }
];
var menuItemsIcan = [
  { payload: '1', text: '[Select an objective]' },
  { payload: '2', text: 'Every Night' },
  { payload: '3', text: 'Weeknights' },
  { payload: '4', text: 'Weekends' },
  { payload: '5', text: 'Weekly' }
];
var menuItemsHousing = [
  { payload: '1', text: '[Select housing]' },
  { payload: '2', text: 'Every Night' },
  { payload: '3', text: 'Weeknights' },
  { payload: '4', text: 'Weekends' },
  { payload: '5', text: 'Weekly' }
];
var menuItemsIlive = [
  { payload: '1', text: '[Select family mambers]' },
  { payload: '2', text: 'Every Night' },
  { payload: '3', text: 'Weeknights' },
  { payload: '4', text: 'Weekends' },
  { payload: '5', text: 'Weekly' }
];
var menuItemsLifestyle = [
  { payload: '1', text: '[Select lifestyle]' },
  { payload: '2', text: 'Every Night' },
  { payload: '3', text: 'Weeknights' },
  { payload: '4', text: 'Weekends' },
  { payload: '5', text: 'Weekly' }
];
var menuItemsLifestyle2 = [
  { payload: '1', text: '[Select savings]' },
  { payload: '2', text: 'Every Night' },
  { payload: '3', text: 'Weeknights' },
  { payload: '4', text: 'Weekends' },
  { payload: '5', text: 'Weekly' }
];
var menuItemsIncome = [
  { payload: '1', text: '[Select your yearly income]' },
  { payload: '2', text: 'Every Night' },
  { payload: '3', text: 'Weeknights' },
  { payload: '4', text: 'Weekends' },
  { payload: '5', text: 'Weekly' }
];
var Content = React.createClass({

  getInitialState: function() {
    return {
      //formData: {
      //  name: '',
      //  age: '',
      //  city: '',
      //  state: ''
      //},
      errorTextName: '',
      errorTextAge: '',
      errorTextCity: '',
      errorTextState: ''
    };
  },

  render: function() {

    return (
      <div className="container-fluid">
        <div className="row color-bg"></div>
        <div className="row main-bg">
          <div className="container">
            <div className="mui-app-content-canvas page-with-nav">
              <div className="page-with-nav-content">

                <Paper zDepth={1}>

                  <h2 className="title-h2">Now, what would you like to do?</h2>

                  <Toolbar>
                    <ToolbarGroup key={1} float="right">
                      <span>I want to</span>
                      <DropDownMenu
                        className="dropdown-long"
                        menuItems={menuItemsIwant}
                        //autoWidth={false}
                      />
                    </ToolbarGroup>
                  </Toolbar>

                  <div className="clearfix"></div>

                  <Toolbar>
                    <ToolbarGroup key={2} float="right">
                      <span>So I can</span>
                      <DropDownMenu
                        className="dropdown-long"
                        menuItems={menuItemsIcan}
                        //autoWidth={false}
                      />
                    </ToolbarGroup>
                  </Toolbar>

                  <h2 className="title-h2">Please, share a little about you.</h2>

                  <div className="clearfix"></div>

                  <Toolbar>
                    <ToolbarGroup key={3} float="right">
                      <span>I am</span>
                      <TextField
                        id="name"
                        className="text-field-long"
                        ref="textfield"
                        hintText="Full name"
                        errorText={this.state.errorTextName}
                        onChange={this._handleErrorInputChange}
                      />
                      <span>and I am</span>
                      <TextField
                        id="age"
                        className="text-field-short"
                        ref="textfield"
                        hintText="00"
                        errorText={this.state.errorTextAge}
                        onChange={this._handleErrorInputChange}
                      />
                      <span className="span-right-measure">years of age.</span>
                    </ToolbarGroup>
                  </Toolbar>

                  <div className="clearfix"></div>

                  <Toolbar>
                    <ToolbarGroup key={4} float="right">
                      <span>I</span>
                      <DropDownMenu
                        hintText="I"
                        menuItems={menuItemsHousing}
                        //autoWidth={false}
                      />
                      <span>in</span>
                      <TextField
                        id="city"
                        ref="textfield"
                        className="text-field-long"
                        hintText="City"
                        errorText={this.state.errorTextCity}
                        onChange={this._handleErrorInputChange}
                      />
                      <span>,</span>
                      <TextField
                        id="state"
                        ref="textfield"
                        className="text-field-short text-field-right-measure"
                        hintText="ST"
                        errorText={this.state.errorTextState}
                        onChange={this._handleErrorInputChange}
                      />
                    </ToolbarGroup>
                  </Toolbar>

                  <div className="clearfix"></div>

                  <Toolbar>
                    <ToolbarGroup key={5} float="right">
                      <span>Where I live</span>
                      <DropDownMenu
                        className="dropdown-long"
                        menuItems={menuItemsIlive}
                        //autoWidth={false}
                      />
                    </ToolbarGroup>
                  </Toolbar>

                  <div className="clearfix"></div>

                  <Toolbar>
                    <ToolbarGroup key={6} float="right">
                      <span>My lifestyle is</span>
                      <DropDownMenu
                        className="dropdown-short"
                        menuItems={menuItemsLifestyle}
                        //autoWidth={false}
                      />
                      <span>and I've saved</span>
                      <DropDownMenu
                        className="dropdown-short"
                        menuItems={menuItemsLifestyle2}
                        //autoWidth={false}
                      />
                    </ToolbarGroup>
                  </Toolbar>

                  <div className="clearfix"></div>

                  <Toolbar>
                    <ToolbarGroup key={7} float="right">
                      <span>My yearly household is about</span>
                      <DropDownMenu
                        className="dropdown-mobile"
                        menuItems={menuItemsIncome}
                        //autoWidth={false}
                      />
                    </ToolbarGroup>
                  </Toolbar>

                  <div className="clearfix"></div>

                  <div className="button-place">
                    <FlatButton
                      onTouchTap={this._handleClick}
                      label="I'm done lets go!"
                    />

                    <Snackbar
                      ref="snackbar"
                      message="Invalid input, please check and try again"
                    />
                  </div>

                </Paper>

              </div>
            </div>
          </div>
        </div>
      </div>
    );
  },

  _handleErrorInputChange: function(e) {
    if (e.target.id === 'name') {
      var name = e.target.value;
      this.setState({
        //name: name,
        errorTextName: e.target.value ? '' : 'Please, type your Name'
      });
    } else if (e.target.id === 'age') {
      var age = e.target.value;
      this.setState({
        //age: age,
        errorTextAge: e.target.value ? '' : 'Check Age'
      });
    } else if (e.target.id === 'city') {
      var city = e.target.value;
      this.setState({
        //city: city,
        errorTextCity: e.target.value ? '' : 'Type City'
      });
    } else if (e.target.id === 'state') {
      var state = e.target.value;
      this.setState({
        //state: state,
        errorTextState: e.target.value ? '' : 'Type State'
      });
    }
  },

  _handleClick: function(e) {
    this.refs.snackbar.show();
    //TODO: find a way to change errorText for all empty TextField
    if (this.refs.textfield && this.refs.textfield.getValue().length === 0) {
      this.setState({
        errorTextState: 'Type State',
        errorTextCity: 'Type City',
        errorTextAge: 'Check Age',
        errorTextName: 'Please, type your Name'
      });
    }
  }

});

module.exports = Content;

我想通过_handleClick方法将其发送到服务器上。

Answers:


83

onChange向您的TextFieldDropDownMenu元素中的每个添加处理程序。当它被调用时,在保存这些输入的新的价值state你的Content组件。在渲染中,从中检索这些值state并将其作为valueprop传递。请参阅受控组件

var Content = React.createClass({

    getInitialState: function() {
        return {
            textFieldValue: ''
        };
    },

    _handleTextFieldChange: function(e) {
        this.setState({
            textFieldValue: e.target.value
        });
    },

    render: function() {
        return (
            <div>
                <TextField value={this.state.textFieldValue} onChange={this._handleTextFieldChange} />
            </div>
        )
    }

});

现在,您在_handleClick方法中要做的就是从中检索所有输入的值this.state并将其发送到服务器。

您也可以使用React.addons.LinkedStateMixin来简化此过程。请参阅双向绑定帮助器。先前的代码变为:

var Content = React.createClass({

    mixins: [React.addons.LinkedStateMixin],

    getInitialState: function() {
        return {
            textFieldValue: ''
        };
    },

    render: function() {
        return (
            <div>
                <TextField valueLink={this.linkState('textFieldValue')} />
            </div>
        )
    }

});

值得注意的是,onChange将使用以下参数调用DropDownMenu组件的处理程序:eventkeypayload。有效负载是所选MenuItem值。键是MenuItem的索引。参见源代码:github.com/callemall/material-ui/blob/master/src/DropDownMenu/…–
Mido

2
引用react文档:从React v15开始不推荐使用ReactLink。建议不要使用ReactLink显式设置值并更改处理程序。facebook.github.io/react/docs/two-way-binding-helpers.html
sebastienbarbier

为什么在_handleTextFieldChange下划线?
丹尼斯

1
@ Mr.White只是一种样式惯例,因为我们认为该方法是私有的,即从该组件的上下文外部调用它是没有意义的。我个人没有强制执行该约定,我只是重用了Vitalii问题中的代码示例。
亚历山大·柯森伯格

当用户一键输入字符时,会触发onChange事件并调用setState来更新值,然后一次又一次调用render,因此,在键入时,用户会感觉很慢并且卡住了。如何避免这种情况?
dush88c

74

使用接受的答案/这是另一个(已删除)问题的答案

@karopastal

ref向您的<TextField />组件添加一个属性,并在其上调用getValue(),如下所示:

零件:

<TextField ref="myField" />

使用getValue:

this.refs.myField.getValue()

2
这种方法更好
可以。

2
@flson不适用于下拉菜单,您如何处理下拉菜单。但是可以与其余组件一起使用。打开了另一个问题,如果您有答案,请帮助我。链接:stackoverflow.com/questions/32633272/…–
rosnk


2
使用此方法,setState始终落后一步。我不得不恢复使用value和onChange。
thetrystero'2015-10-29

4
使用this.refs已经/正在被淘汰,使用受控的部件。不要使用这个。
rkstar

6

flson的代码对我不起作用。对于那些处于类似情况的人,这是我略有不同的代码:

<TextField ref='myTextField'/>

获得其价值

this.refs.myTextField.input.value


4

可接受的答案的策略是正确的,但是这是一个适用于当前版本的React和Material-UI的通用示例。

数据流应该是单向的:

  • initialState在MyForm控件的构造函数中初始化
  • 所述TextAreas的从该初始状态填充
  • 对TextAreas的更改将state通过handleChange回调传播到。
  • state从访问onClick回调---现在它只是写入控制台。如果您想添加验证,可以去那里。
import * as React from "react";
import TextField from "material-ui/TextField";
import RaisedButton from "material-ui/RaisedButton";

const initialState = {
    error: null, // you could put error messages here if you wanted
    person: {
        firstname: "",
        lastname: ""
    }
};

export class MyForm extends React.Component {

    constructor(props) {
        super(props);
        this.state = initialState;
        // make sure the "this" variable keeps its scope
        this.handleChange = this.handleChange.bind(this);
        this.onClick = this.onClick.bind(this);
    }

    render() {
        return (
            <div>
                <div>{this.state.error}</div>
                <div>
                    <TextField
                        name="firstname"
                        value={this.state.person.firstname}
                        floatingLabelText="First Name"
                        onChange={this.handleChange}/>
                    <TextField
                        name="lastname"
                        value={this.state.person.lastname}
                        floatingLabelText="Last Name"
                        onChange={this.handleChange}/>
                </div>
                <div>
                    <RaisedButton onClick={this.onClick} label="Submit!" />
                </div>
            </div>
        );
    }

    onClick() {
        console.log("when clicking, the form data is:");
        console.log(this.state.person);
    }

    handleChange(event, newValue): void {
        event.persist(); // allow native event access (see: https://facebook.github.io/react/docs/events.html)
        // give react a function to set the state asynchronously.
        // here it's using the "name" value set on the TextField
        // to set state.person.[firstname|lastname].            
        this.setState((state) => state.person[event.target.name] = newValue);

    }

}


React.render(<MyForm />, document.getElementById('app'));

(注意:您可能希望为handleChange每个MUI组件编写一个回调,以消除该丑陋的event.persist()调用。)


4

自从在这里问了很长时间以来就面对这个问题。在检查材料用户界面代码时,我发现它现在可以通过inputRef属性访问。

...
<CssTextField
  inputRef={(c) => {this.myRefs.username = c}}
  label="Username"
  placeholder="xxxxxxx"
  margin="normal"
  className={classes.textField}
  variant="outlined"
  fullWidth
/>
...

然后访问这样的值。

  onSaveUser = () => {
    console.log('Saving user');
    console.log(this.myRefs.username.value);
  }

我认为这需要成为2020
HirdayGupta

3

这是我想到的最简单的解决方案,我们获得了material-ui textField创建的输入的值:

      create(e) {
        e.preventDefault();
        let name = this.refs.name.input.value;
        alert(name);
      }

      constructor(){
        super();
        this.create = this.create.bind(this);
      }

      render() {
        return (
              <form>
                <TextField ref="name" hintText="" floatingLabelText="Your name" /><br/>
                <RaisedButton label="Create" onClick={this.create} primary={true} />
              </form>
        )}

希望这可以帮助。


3

这里所有的解决方案都是基于Class Component的,但是我想大多数最近学习React的人(像我一样),这次是使用功能性的Component。因此,这里是基于功能组件的解决方案。

使用ReactJs的useRef钩子和TextField的inputRef属性。

    import React, { useRef, Component } from 'react'
    import { TextField, Button } from '@material-ui/core'
    import SendIcon from '@material-ui/icons/Send'

    export default function MultilineTextFields() {
    const valueRef = useRef('') //creating a refernce for TextField Component

    const sendValue = () => {
        return console.log(valueRef.current.value) //on clicking button accesing current value of TextField and outputing it to console 
    }

    return (
        <form noValidate autoComplete='off'>
        <div>
            <TextField
            id='outlined-textarea'
            label='Content'
            placeholder='Write your thoughts'
            multiline
            variant='outlined'
            rows={20}
            inputRef={valueRef}   //connecting inputRef property of TextField to the valueRef
            />
            <Button
            variant='contained'
            color='primary'
            size='small'
            endIcon={<SendIcon />}
            onClick={sendValue}
            >
            Send
            </Button>
        </div>
        </form>
    )
    }

属性“值”在类型“字符串”上不存在。
哈什·普杰达尔

Component如果您正在使用功能组件,则无需从React导入。
Yaakov Ainspan

2

我不知道所有这些,但出于我自己的懒惰目的,我只是通过ID从“文档”中获取了文本字段,并将这些值设置为我的后端JS函数的参数:

//index.js

      <TextField
        id="field1"
        ...
      />

      <TextField
        id="field2"
        ...
      />

      <Button
      ...
      onClick={() => { printIt(document.getElementById('field1').value,
      document.getElementById('field2').value)    
      }}>


//printIt.js

export function printIt(text1, text2) {
console.log('on button clicked');
alert(text1);
alert(text2);
};

它工作正常。


这是不受控制的组件的示例,这很好,但根据文档不建议使用。
DSL

0
class Content extends React.Component {
    render() {
        return (
            <TextField ref={(input) => this.input = input} />
        );
    }

    _doSomethingWithData() {
        let inputValue =  this.input.getValue();
    }
}

2
这是什么,应该放在哪里?它有什么作用?如果没有其他上下文,此答案无济于事?
亚当

0

2020年,针对TextField,通过功能组件:

const Content = () => {
   ... 
      const textFieldRef = useRef();

      const readTextFieldValue = () => {
        console.log(textFieldRef.current.value)
      }
   ...
  
      return(
       ...
       <TextField
        id="myTextField"
        label="Text Field"
        variant="outlined"
        inputRef={textFieldRef}
       />
       ...
      )

}

请注意,这不是完整的代码。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.