Redux-form: как отключить кнопку отправки, если хотя бы одно поле недействительно?
Я представляю простую форму ниже с помощью редукционной формы, и она отлично работает. Теперь я бы хотел, чтобы кнопка отправки была отключена в еще одной ситуации: Если какая-либо из Field
имеет ошибку (т.е. Она meta.error
установлена).
Из lokking в документы, я полагаю, что окружающим <form>
не известно, есть ли в его компонентах <Field>
ошибка. Может быть, у кого-то есть идея, как решить ее так же просто, как использовать disabled={hasErrors || submitting || pristine}
const EditBlogEntryForm = ({ onSubmit, reset, handleSubmit,
pristine, submitting, ...rest }) => {
console.log('rest: ', rest);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div className="form-group">
<Field name="title"
type="text"
component={renderField}
label="Titel"
className="form-control"
placeholder="Titel eingeben..." />
</div>
<div className="form-group">
<Field name="text"
component={renderTextArea}
label="Text"
className="form-control"
placeholder="Textinhalt eingeben..." />
</div>
<div className="form-group">
<Field name="image"
type="text"
component={renderField}
label="Bild-URL:"
className="form-control"
placeholder="Bildadresse eingeben..." />
</div>
<div>
<button type="submit" className="btn btn-default"
disabled={submitting || pristine}>
Blogeintrag speichern
</button>
<button type="button" className="btn btn-default"
disabled={pristine || submitting}
onClick={reset}>
Formular leeren
</button>
</div>
</form>
);
};
Ответы
Ответ 1
Не злоупотребляйте состоянием, которое вам нужно, просто используя this.props для каждого компонента setState еще раз
const {invalid} = this.props
return(
<button type="submit" className="btn btn-default"
disabled={invalid|| submitting || pristine}>
Blogeintrag speichern
</button>)
Дополнительный документ: https://redux-form.com/6.0.0-alpha.4/docs/api/props.md/
Ответ 2
То, что вы должны сделать, это просто иметь переменные с именем Errors
, которые будут истинны, как только ваш api-вызов вернется с ошибкой
constructor(super) {
this.state = {
errors: false,
}
}
componentWillReceiveProps(nextProps) {
const that = this;
if (nextProps.errors) {
that.setState({errors: true})
}
}
<button type="submit" className="btn btn-default"
disabled={this.state.errors || submitting || pristine}>
Blogeintrag speichern
</button>
Ответ 3
Redux формы уже передают множество свойств в форму. Один invalid
. Это то, что я использую, чтобы определить, не прошла ли проверка полей, а затем отключить отправку.
https://redux-form.com/6.0.0-alpha.4/docs/api/props.md/
Ответ 4
Аластер указал мне правильное направление (спасибо за это!). Я предполагаю, что это один из случаев, когда локальное состояние, связанное с пользовательским интерфейсом, действительно очень полезно. Поэтому я реорганизовал SFC в класс реагирования. Эти классы constructor
и componentWillReceiveProps
выглядят следующим образом:
constructor(props) {
super(props);
this.state = {
errors: false
};
}
componentWillReceiveProps(nextProps) {
if (nextProps.invalid) {
this.setState({errors: true});
} else {
this.setState({errors: false});
}
}
Теперь использование this.state.errors
для отключения кнопки работает отлично. Как вы можете видеть, мне пришлось использовать форму реквизита invalid
prop, поскольку его error
prop всегда undefined и не забывать снова устанавливать его true, если форма действительна. Кроме того, я не знаю, почему вы скопировали ссылку this
в that
в своем ответе. Это не изменит никакого поведения, поскольку оно все еще указывает на тот же объект.
Ответ 5
Возможность использования поля проверки. Вам нужно определить функцию:
const required = value => (value? undefined: 'Required')
И используйте эту функцию в своей области:
<div className="form-group">
<Field name="title"
type="text"
component={renderField}
label="Titel"
className="form-control"
placeholder="Titel eingeben..."
validate={[required]}
/>
</div>
Ответ 6
Если вы используете библиотеку react-redux-form
вы можете в конечном итоге использовать событие onUpdate
в форме для захвата состояния действительности формы, и таким образом вы можете изменить некоторую внутреннюю переменную состояния, которая может использоваться для деактивации кнопки. Вот пример кода, демонстрирующий, что вы можете сделать:
import React, { Component } from 'react';
import { Button, Modal, ModalHeader, ModalBody, Row, Label, Col } from 'reactstrap';
import { Control, LocalForm, Errors } from 'react-redux-form';
const required = (val) => val && val.length;
const maxLength = (len) => (val) => !(val) || (val.length <= len);
const minLength = (len) => (val) => (val) && (val.length >= len);
class CommentForm extends Component {
constructor(props) {
super(props);
this.state = {
isModalOpen: false,
isFormInValid: true
};
this.toggleModal = this.toggleModal.bind(this);
}
toggleModal() {
this.setState({
isModalOpen: !this.state.isModalOpen
})
}
handleSubmit(values) {
console.log("Current state is: " + JSON.stringify(values));
alert(JSON.stringify(values));
}
handleUpdate(form) {
this.setState({ isFormInValid: !form['$form'].valid });
}
render() {
return (
<>
<Button outline onClick={this.toggleModal}>
<span className="fa fa-pencil fa-lg"></span> Submit Comment
</Button>
<Modal isOpen={this.state.isModalOpen} toggle={this.toggleModal}>
<ModalHeader toggle={this.toggleModal}>Submit Comment</ModalHeader>
<ModalBody>
<LocalForm
onUpdate={(form) => this.handleUpdate(form)}
onSubmit={(values) => this.handleSubmit(values)}>
<Row className="form-group">
<Label htmlFor="author" md={12}>Your Name</Label>
<Col md={12}>
<Control.text model=".author" id="author" name="author"
placeholder="First Name" className="form-control"
validators={{ required, minLength: minLength(3), maxLength: maxLength(15) }} />
<Errors className="text-danger" model=".author" show="touched"
messages={{ required: 'Required ', minLength: 'Must be greater than 2 characters', maxLength: 'Must be 15 characters or less' }} />
</Col>
</Row>
<Row className="form-group">
<Col md={12}>
<Button type="submit" color="primary" disabled={this.state.isFormInValid}>Submit</Button>
</Col>
</Row>
</LocalForm>
</ModalBody>
</Modal>
</>
);
}
}