У меня есть простая форма в моей функции render
, например:
render : function() {
return (
<form>
<input type="text" name="email" placeholder="Email" />
<input type="password" name="password" placeholder="Password" />
<button type="button" onClick={this.handleLogin}>Login</button>
</form>
);
},
handleLogin: function() {
//How to access email and password here ?
}
Что мне следует писать в handleLogin: function() { ... }
для доступа к полям Email
и Password
?
Используйте события change
на входах для обновления состояния компонента и доступа к нему в handleLogin
:
handleEmailChange: function(e) {
this.setState({email: e.target.value});
},
handlePasswordChange: function(e) {
this.setState({password: e.target.value});
},
render : function() {
return (
<form>
<input type="text" name="email" placeholder="Email" value={this.state.email} onChange={this.handleEmailChange} />
<input type="password" name="password" placeholder="Password" value={this.state.password} onChange={this.handlePasswordChange}/>
<button type="button" onClick={this.handleLogin}>Login</button>
</form>);
},
handleLogin: function() {
console.log("EMail: " + this.state.email);
console.log("Password: " + this.state.password);
}
Рабочая скрипка: http://jsfiddle.net/kTu3a/
Кроме того, прочитайте документы, есть целый раздел, посвященный обработке формы: http://facebook.github.io/react/docs/forms.html
Раньше вы могли также использовать React для двусторонней настройки привязки databinding helper mixin для достижения того же, но теперь он устарел в пользу установки обработчика значения и изменения (как указано выше):
var ExampleForm = React.createClass({
mixins: [React.addons.LinkedStateMixin],
getInitialState: function() {
return {email: '', password: ''};
},
handleLogin: function() {
console.log("EMail: " + this.state.email);
console.log("Password: " + this.state.password);
},
render: function() {
return (
<form>
<input type="text" valueLink={this.linkState('email')} />
<input type="password" valueLink={this.linkState('password')} />
<button type="button" onClick={this.handleLogin}>Login</button>
</form>
);
}
});
Документация находится здесь: http://facebook.github.io/react/docs/two-way-binding-helpers.html
onchange
v / s и mixin?
Есть несколько способов сделать это:
1) Получить значения из массива элементов формы по индексу
handleSubmit = (event) => {
event.preventDefault();
console.log(event.target[0].value)
}
2) Использование атрибута name в html
handleSubmit = (event) => {
event.preventDefault();
console.log(event.target.elements.username.value) // from elements property
console.log(event.target.username.value) // or directly
}
<input type="text" name="username"/>
3) Использование ссылок
handleSubmit = (event) => {
console.log(this.inputNode.value)
}
<input type="text" name="username" ref={node => (this.inputNode = node)}/>
Полный пример
class NameForm extends React.Component {
handleSubmit = (event) => {
event.preventDefault()
console.log(event.target[0].value)
console.log(event.target.elements.username.value)
console.log(event.target.username.value)
console.log(this.inputNode.value)
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input
type="text"
name="username"
ref={node => (this.inputNode = node)}
/>
</label>
<button type="submit">Submit</button>
</form>
)
}
}
Альтернативный подход - использовать атрибут ref
и ссылаться на значения с помощью this.refs
. Вот простой пример:
render: function() {
return (<form onSubmit={this.submitForm}>
<input ref="theInput" />
</form>);
},
submitForm: function(e) {
e.preventDefault();
alert(React.findDOMNode(this.refs.theInput).value);
}
Дополнительную информацию можно найти в документации React: https://facebook.github.io/react/docs/more-about-refs.html#the-ref-string-attribute.
По многим причинам, описанным в разделе Как использовать переключатели в React? этот подход не всегда лучший, но он представляет полезную альтернативу в некоторых простых случаях.
Простой способ справиться с refs:
class UserInfo extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(e) {
e.preventDefault();
const formData = {};
for (const field in this.refs) {
formData[field] = this.refs[field].value;
}
console.log('-->', formData);
}
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<input ref="phone" className="phone" type='tel' name="phone"/>
<input ref="email" className="email" type='tel' name="email"/>
<input type="submit" value="Submit"/>
</form>
</div>
);
}
}
export default UserInfo;
Object.keys()
за которым следует map()
например: Object.keys(this.refs).map(field => formData[field] = this.refs[field].value)
Я бы предложил следующий подход:
import {Autobind} from 'es-decorators';
export class Form extends Component {
@Autobind
handleChange(e) {
this.setState({[e.target.name]: e.target.value});
}
@Autobind
add(e) {
e.preventDefault();
this.collection.add(this.state);
this.refs.form.reset();
}
shouldComponentUpdate() {
return false;
}
render() {
return (
<form onSubmit={this.add} ref="form">
<input type="text" name="desination" onChange={this.handleChange}/>
<input type="date" name="startDate" onChange={this.handleChange}/>
<input type="date" name="endDate" onChange={this.handleChange}/>
<textarea name="description" onChange={this.handleChange}/>
<button type="submit">Add</button>
</form>
)
}
}
Вы можете переключить обработчик событий onClick
на кнопку на обработчик onSubmit
в форме:
render : function() {
return (
<form onSubmit={this.handleLogin}>
<input type="text" name="email" placeholder="Email" />
<input type="password" name="password" placeholder="Password" />
<button type="submit">Login</button>
</form>
);
},
Затем вы можете использовать FormData
для разбора формы (и, если хотите, построить объект JSON из своих записей).
handleLogin: function(e) {
const formData = new FormData(e.target)
const user = {}
e.preventDefault()
for (let entry of formData.entries()) {
user[entry[0]] = entry[1]
}
// Do what you will with the user object here
}
Если у всех ваших входов/текстовой области есть имя, вы можете отфильтровать все из event.target:
onSubmit(event){
const fields = Array.prototype.slice.call(event.target)
.filter(el => el.name)
.reduce((form, el) => ({
...form,
[el.name]: el.value,
}), {})
}
Полностью неконтролируемая форма form без методов onChange, value, defaultValue...
Дайте ваши ссылки, как это
<input type="text" name="email" placeholder="Email" ref="email" />
<input type="password" name="password" placeholder="Password" ref="password" />
тогда вы можете получить к нему доступ в своем дескрипторе, как Су
handleLogin: function(e) {
e.preventDefault();
console.log(this.refs.email.value)
console.log(this.refs.password.value)
}
onChange(event){
console.log(event.target.value);
}
handleSubmit(event){
event.preventDefault();
const formData = {};
for (const data in this.refs) {
formData[data] = this.refs[data].value;
}
console.log(formData);
}
<form onSubmit={this.handleSubmit.bind(this)}>
<input type="text" ref="username" onChange={this.onChange} className="form-control"/>
<input type="text" ref="password" onChange={this.onChange} className="form-control"/>
<button type="submit" className="btn-danger btn-sm">Search</button>
</form>
Во многих событиях в javascript мы имеем event
, которые дают объект, включая то, что произошло, и каковы значения и т.д.
То, что мы используем с формами в ReactJs, также...
Итак, в коде вы устанавливаете состояние в новое значение... что-то вроде этого:
class UserInfo extends React.Component {
constructor(props) {
super(props);
this.handleLogin = this.handleLogin.bind(this);
}
handleLogin(e) {
e.preventDefault();
for (const field in this.refs) {
this.setState({this.refs[field]: this.refs[field].value});
}
}
render() {
return (
<div>
<form onSubmit={this.handleLogin}>
<input ref="email" type="text" name="email" placeholder="Email" />
<input ref="password" type="password" name="password" placeholder="Password" />
<button type="button">Login</button>
</form>
</div>
);
}
}
export default UserInfo;
Также это пример формы в React v.16, как ссылка для формы, которую вы создаете в будущем:
class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: ''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('A name was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
Если вы используете Redux в своем проекте, вы можете использовать этот компонент более высокого порядка https://github.com/erikras/redux-form.
Кроме того, это также можно использовать.
handleChange: function(state,e) {
this.setState({[state]: e.target.value});
},
render : function() {
return (
<form>
<input type="text" name="email" placeholder="Email" value={this.state.email} onChange={this.handleChange.bind(this, 'email')} />
<input type="password" name="password" placeholder="Password" value={this.state.password} onChange={this.handleChange.bind(this, 'password')}/>
<button type="button" onClick={this.handleLogin}>Login</button>
</form>
);
},
handleLogin: function() {
console.log("EMail: ", this.state.email);
console.log("Password: ", this.state.password);
}
Более наглядный пример с разрушением es6
class Form extends Component {
constructor(props) {
super(props);
this.state = {
login: null,
password: null,
email: null
}
}
onChange(e) {
this.setState({
[e.target.name]: e.target.value
})
}
onSubmit(e) {
e.preventDefault();
let login = this.state.login;
let password = this.state.password;
// etc
}
render() {
return (
<form onSubmit={this.onSubmit.bind(this)}>
<input type="text" name="login" onChange={this.onChange.bind(this)} />
<input type="password" name="password" onChange={this.onChange.bind(this)} />
<input type="email" name="email" onChange={this.onChange.bind(this)} />
<button type="submit">Sign Up</button>
</form>
);
}
}
Это может помочь пользователям Meteor (v1.3):
render: function() {
return (
<form onSubmit={this.submitForm.bind(this)}>
<input type="text" ref="email" placeholder="Email" />
<input type="password" ref="password" placeholder="Password" />
<button type="submit">Login</button>
</form>
);
},
submitForm: function(e) {
e.preventDefault();
console.log( this.refs.email.value );
console.log( this.refs.password.value );
}
Если у вас есть несколько вхождений имени элемента, вы должны использовать forEach().
HTML
<input type="checkbox" name="delete" id="flizzit" />
<input type="checkbox" name="delete" id="floo" />
<input type="checkbox" name="delete" id="flum" />
<input type="submit" value="Save" onClick={evt => saveAction(evt)}></input>
JS
const submitAction = (evt) => {
evt.preventDefault();
const dels = evt.target.parentElement.delete;
const deleted = [];
dels.forEach((d) => { if (d.checked) deleted.push(d.id); });
window.alert(deleted.length);
};
Обратите внимание, что dels в этом случае является RadioNodeList, а не массивом, и не является Iterable. ForEach() является встроенным методом класса списка. Вы не сможете использовать карту() или уменьшить() здесь.
Улучшить работу пользователя; когда пользователь нажимает кнопку отправки, вы можете попытаться получить форму, чтобы сначала показать отправленное сообщение. Как только мы получим ответ от сервера, он может соответствующим образом обновить сообщение. Мы достигаем этого в Реактировании, связывая статусы. См. codepen или ниже:
Следующий способ делает первое изменение состояния:
handleSubmit(e) {
e.preventDefault();
this.setState({ message: 'Sending...' }, this.sendFormData);
}
Как только React отобразит вышеуказанное сообщение отправки на экране, он вызовет метод, который будет отправлять данные формы на сервер: this.sendFormData(). Для простоты я добавил setTimeout, чтобы имитировать это.
sendFormData() {
var formData = {
Title: this.refs.Title.value,
Author: this.refs.Author.value,
Genre: this.refs.Genre.value,
YearReleased: this.refs.YearReleased.value};
setTimeout(() => {
console.log(formData);
this.setState({ message: 'data sent!' });
}, 3000);
}
В React метод this.setState() отображает компонент с новыми свойствами. Таким образом, вы также можете добавить некоторую логику в метод render() компонента формы, который будет вести себя по-разному в зависимости от типа ответа, который мы получаем с сервера. Например:
render() {
if (this.state.responseType) {
var classString = 'alert alert-' + this.state.type;
var status = <div id="status" className={classString} ref="status">
{this.state.message}
</div>;
}
return ( ...
action
и обрабатываться вашим бэкэндом должным образом.button
должна бытьtype="submit"
, и вместо этого обработчик должен бытьonsubmit
на форму. Используйте формы, разработанные в HTML, и ваши пользователи получат пользу.