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