【问题标题】:How get data from material-ui TextField, DropDownMenu components?如何从material-ui TextField、DropDownMenu组件中获取数据?
【发布时间】:2015-06-29 18:23:05
【问题描述】:

我创建了表单,我有几个 TextField、DropDownMenu material-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 方法在服务器上发送它。

【问题讨论】:

    标签: javascript reactjs material-design material-ui


    【解决方案1】:

    为每个TextFieldDropDownMenu 元素添加一个onChange 处理程序。当它被调用时,将这些输入的新值保存在您的Content 组件的state 中。在渲染中,从state 检索这些值并将它们作为value 属性传递。见Controlled Components

    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 来简化此过程。见Two-Way Binding Helpers。之前的代码变成:

    var Content = React.createClass({
    
        mixins: [React.addons.LinkedStateMixin],
    
        getInitialState: function() {
            return {
                textFieldValue: ''
            };
        },
    
        render: function() {
            return (
                <div>
                    <TextField valueLink={this.linkState('textFieldValue')} />
                </div>
            )
        }
    
    });
    

    【讨论】:

    • 值得注意的是,DropDownMenu 组件的onChange 处理程序将使用以下参数调用:eventkey有效载荷。 Payload 是选定的MenuItem 的值。键是MenuItem 的索引。见源:github.com/callemall/material-ui/blob/master/src/DropDownMenu/…
    • 引用 react 文档:从 React v15 开始,ReactLink 已被弃用。建议是显式设置值和更改处理程序,而不是使用 ReactLink。 facebook.github.io/react/docs/two-way-binding-helpers.html
    • 为什么 _handleTextFieldChange 中有下划线?
    • @Mr.White 只是一种风格约定,因为我们认为该方法是私有的,即从该组件的上下文之外调用它是没有意义的。我个人并没有强制执行这个约定,我只是重用了 Vitalii 问题中的代码示例。
    • 当用户一个一个地输入字符时,会触发 onChange 事件并调用 setState 来更新值,然后一次又一次地调用 render,所以当用户输入时感觉输入缓慢和卡顿。如何避免这种情况?
    【解决方案2】:

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

    @karopastal

    ref 属性添加到您的&lt;TextField /&gt; 组件并对其调用getValue(),如下所示:

    组件:

    <TextField ref="myField" />
    

    使用 getValue:

    this.refs.myField.getValue()
    

    【讨论】:

    • 这个方法比较好
    • @flson 它不适用于下拉菜单,您如何处理下拉菜单。虽然适用于组件的其余部分。已打开另一个问题,如果您有答案,请帮助我。链接:stackoverflow.com/questions/32633272/…
    • 使用 refs 是不是很糟糕? stackoverflow.com/questions/29503213/…
    • 使用这种方法,setState总是落后一步。我不得不恢复使用 value 和 onChange。
    • 使用this.refs 已被/正在被弃用,以支持使用受控组件。不要使用这个。
    【解决方案3】:

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

    &lt;TextField ref='myTextField'/&gt;

    使用

    获取它的值

    this.refs.myTextField.input.value

    【讨论】:

      【解决方案4】:
      class Content extends React.Component {
          render() {
              return (
                  <TextField ref={(input) => this.input = input} />
              );
          }
      
          _doSomethingWithData() {
              let inputValue =  this.input.getValue();
          }
      }
      

      【讨论】:

      • 这是什么,应该放在哪里?它有什么作用?如果没有额外的上下文,这个答案没有帮助吗?
      【解决方案5】:

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

      数据流应该是单向的:

      • initialState 在 MyForm 控件的构造函数中初始化
      • TextAreas 是从此初始状态填充的
      • 对 TextAreas 的更改通过 handleChange 回调传播到 state
      • 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'));
      

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

      【讨论】:

        【解决方案6】:

        这是我想出的最简单的解决方案,我们得到由 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>
                )}
        

        希望这会有所帮助。

        【讨论】:

          【解决方案7】:

          自从这里提出问题以来很长时间后面临这个问题。检查 material-ui 代码时,我发现它现在可以通过 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 年公认的答案
          【解决方案8】:

          我不了解你们,但出于我自己懒惰的目的,我只是通过 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);
          };

          效果很好。

          【讨论】:

          • 这是一个不受控制的组件的例子,这很好,但根据文档不推荐。
          【解决方案9】:

          这里所有的解决方案都是基于Class Component, 但我猜大多数最近学习 React 的人(比如我), 这时候使用功能组件。 所以这里是基于功能组件的解决方案。

          使用 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>
              )
              }
          

          【讨论】:

          • “字符串”类型上不存在属性“值”。
          • 如果你使用的是函数式组件,你不需要从 React 导入Component
          【解决方案10】:

          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}
                 />
                 ...
                )
          
          }
          

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

          【讨论】:

            【解决方案11】:

            试试这个,

            import React from 'react';
            import {useState} from 'react';
            
            import TextField from '@material-ui/core/TextField';
            
            const Input = () => {
                const [textInput, setTextInput] = useState('');
            
                const handleTextInputChange = event => {
                    setTextInput(event.target.value);
                };
                
                return(
                    <TextField
                        label="Text Input"
                        value= {textInput}
                        onChange= {handleTextInputChange}
                    />
                );
            }
            
            export default Input;
            
            

            如果上面的代码不清楚,请说明。

            首先,我们创建一个状态来存储名为 textInput 的文本输入,并将其赋值为 ''。

            然后我们返回一个材质 UI &lt;TextField /&gt; 组件,其 value 属性设置为 textInput 状态。这样做我们会在&lt;TextField /&gt; 中显示textInput 的当前值。对 textInput 值的任何更改都会更改 &lt;TextField /&gt;value 属性,由 React 提供。

            然后我们使用&lt;TextField /&gt;onChange属性在每次&lt;TextField /&gt;value属性的值发生变化时运行一个处理函数。这个处理函数是一个箭头函数,存储在常量handleTextInputChange中。它需要一个 事件 作为参数。当 onChange 属性运行处理函数时,它会将 事件 作为参数发送给处理函数。

            &lt;TextField /&gt; 的值存储在 event.target.value 中。然后我们使用状态的setTextInput 方法将状态设置为&lt;TextField /&gt;value 属性。因此,这种变化反映在 &lt;TextField /&gt; 中,其 value 属性是 textInput 状态的值。

            因此,输入到&lt;TextField /&gt; 的数据存储在状态textInput 中,可以在需要时使用。

            【讨论】:

            • 您可以为您的解决方案添加解释吗?
            • @SemihArslanoğlu 我已经为我的解决方案添加了解释。我希望你能理解它。
            猜你喜欢
            • 1970-01-01
            • 2020-12-20
            • 1970-01-01
            • 2016-09-15
            • 1970-01-01
            • 2018-07-21
            • 1970-01-01
            • 2021-09-12
            • 1970-01-01
            相关资源
            最近更新 更多