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

我创建表单,我有几个 TextField,DropDownMenu 材料-ui 组件包括在内,问题是我如何能够收集所有的 TextFields,DropDownMenus 在一个 obj 中的所有数据,并发送到服务器上。对于 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 方法的服务器上发送它。

206347 次浏览

Add an onChange handler to each of your TextField and DropDownMenu elements. When it is called, save the new value of these inputs in the state of your Content component. In render, retrieve these values from state and pass them as the value prop. See 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>
)
}


});

Now all you have to do in your _handleClick method is retrieve the values of all your inputs from this.state and send them to the server.

You can also use the React.addons.LinkedStateMixin to make this process easier. See Two-Way Binding Helpers. The previous code becomes:

var Content = React.createClass({


mixins: [React.addons.LinkedStateMixin],


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


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


});

use the accepted answer / this was the answer to another (already deleted) question

@karopastal

add a ref attribute to your <TextField /> component and call getValue() on it, like this:

Component:

<TextField ref="myField" />

Using getValue:

this.refs.myField.getValue()

flson's code did not work for me. For those in the similar situation, here is my slightly different code:

<TextField ref='myTextField'/>

get its value using

this.refs.myTextField.input.value

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


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

The strategy of the accepted answer is correct, but here's a generalized example that works with the current version of React and Material-UI.

The flow of data should be one-way:

  • the initialState is initialized in the constructor of the MyForm control
  • the TextAreas are populated from this initial state
  • changes to the TextAreas are propagated to the state via the handleChange callback.
  • the state is accessed from the onClick callback---right now it just writes to the console. If you want to add validation it could go there.
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'));

(Note: You may want to write one handleChange callback per MUI Component to eliminate that ugly event.persist() call.)

Here's the simplest solution i came up with, we get the value of the input created by 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>
)}

hope this helps.

Faced to this issue after a long time since question asked here. when checking material-ui code I found it's now accessible through inputRef property.

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

Then Access value like this.

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

I don't know about y'all but for my own lazy purposes I just got the text fields from 'document' by ID and set the values as parameters to my back-end JS function:

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

It works just fine.

Here all solutions are based on Class Component, but i guess most of the people who learned React recently (like me), at this time using functional Component. So here is the solution based on functional component.

Using useRef hooks of ReactJs and inputRef property of TextField.

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

In 2020 for TextField, via functional components:

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


const readTextFieldValue = () => {
console.log(textFieldRef.current.value)
}
...
  

return(
...
<TextField
id="myTextField"
label="Text Field"
variant="outlined"
inputRef={textFieldRef}
/>
...
)


}

Note that this isn't complete code.

Try this,

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;


Explanation if the above code was not clear.

First we create a state to store the text input called textInput and assign it the value ''.

Then we return a material UI <TextField /> component whose value attribute is set to the textInput state. Doing this we display the current value of the textInput in the <TextField />. Any changes to the value of textInput will change the value attribute of the <TextField />, courtesy of React.

Then we use the onChange attribute of <TextField /> to run a handler function every time the value of the <TextField /> value attribute changes. This handler function is an arrow function stored in the constant handleTextInputChange. It takes an event as an argument. When the onChange attribute runs the handler function, it sends the event as an argument to the handler function.

The value of the <TextField /> is stored in event.target.value. We then use the setTextInput method of the state to set the state to the value attribute of the <TextField />. Thus this change is reflected in the <TextField /> whose value attribute is the value of the textInput state.

Thus the data input into the <TextField /> is stored in the state textInput, ready to be used when required.