Проверка формы с помощью react и material-ui

В настоящее время я пытаюсь добавить проверку в форму, созданную с использованием компонентов material-ui. У меня он работает, но проблема в том, что в настоящее время функция проверки вызывается при каждом изменении состояния на входе (т.е. каждой набранной букве). Однако я хочу, чтобы моя проверка происходила только после остановки набора текста.

Учитывая мой текущий код:

class Form extends React.Component {

    state = {open: false, email: '', password: '', email_error_text: null, password_error_text: null, disabled: true};

    handleTouchTap() {
        this.setState({
            open: true,
        });
    }

    isDisabled() {
        let emailIsValid = false;
        let passwordIsValid = false;

        if (this.state.email === "") {
            this.setState({
                email_error_text: null
            });
        } else {
            if (validateEmail(this.state.email)) {
                emailIsValid = true
                this.setState({
                    email_error_text: null
                });
            } else {
                this.setState({
                    email_error_text: "Sorry, this is not a valid email"
                });
            }
        }

        if (this.state.password === "" || !this.state.password) {
            this.setState({
                password_error_text: null
            });
        } else {
            if (this.state.password.length >= 6) {
                passwordIsValid = true;
                this.setState({
                    password_error_text: null
                });
            } else {
                this.setState({
                    password_error_text: "Your password must be at least 6 characters"
                });
            }
        }

        if (emailIsValid && passwordIsValid) {
            this.setState({
                disabled: false
            });
        }
    }

    changeValue(e, type) {
        const value = e.target.value;
        const nextState = {};
        nextState[type] = value;
        this.setState(nextState, () => {
            this.isDisabled()
        });
    }

    login() {
        createUser(this.state.email, this.state.password);
        this.setState({
            open: false
        });
    }

    render() {

        let {open, email, password, email_error_text, password_error_text, disabled} = this.state;

        const standardActions = (
            <FlatButton
                containerElement={<Link to="/portal" />}
                disabled={this.state.disabled}
                label="Submit"
                onClick={this.login.bind(this)} 
            />
        );

        return (
            <div style={styles.container}>
                <Dialog
                    open={this.state.open}
                    title="Enter Your Details to Login"
                    actions={standardActions}
                >
                    <span className="hint--right hint--bounce" data-hint="Enter in your email address">
                        <TextField
                            hintText="Email"
                            floatingLabelText="Email"
                            type="email"
                            errorText={this.state.email_error_text}
                            onChange={e => this.changeValue(e, 'email')} 
                        />
                    </span>
                    <br />
                    <span className="hint--right hint--bounce" data-hint="Enter your password">
                        <TextField
                            hintText="Password"
                            floatingLabelText="Password"
                            type="password"
                            errorText={this.state.password_error_text}
                            onChange={e => this.changeValue(e, 'password')} 
                        />
                    </span>
                </Dialog>
                <h1>VPT</h1>
                <h2>Project DALI</h2>
                <RaisedButton
                    label="Login"
                    primary={true}
                    onTouchTap={this.handleTouchTap.bind(this)} 
                />
            </div>
        );
    }
}

export default Form;

Есть ли способ достичь желаемой функциональности, не внося серьезных изменений в код, или его нужно полностью переработать?


person BeeNag    schedule 28.04.2016    source источник
comment
Я бы очень рекомендовал вам изучить для этого redux-form.com. вот пример: redux-form.com/5.2.1/# / examples / synchronous-validation   -  person Roman K    schedule 28.04.2016


Ответы (5)


Должна ли проверка происходить с определенной задержкой? Решение, которое, как мне кажется, будет достаточным в большинстве ситуаций, - это немного разделить ваш код. Не запускайте свою isDisabled() функцию в changedValue(). Вместо этого пусть он запускается в событии onBlur.

Попробуй это:

<TextField
  hintText="Password"
  floatingLabelText="Password"
  type="password"
  errorText={this.state.password_error_text}
  onChange={e => this.changeValue(e, 'password')}
  onBlur={this.isDisabled} 
/>

а затем ваша функция станет:

changeValue(e, type) {
    const value = e.target.value;
    const nextState = {};
    nextState[type] = value;
    this.setState(nextState);
}
person Chris    schedule 28.04.2016
comment
На данный момент задержки нет, поэтому сообщение об ошибке будет отображаться до тех пор, пока не будут выполнены параметры проверки, но я хочу выполнить проверку позже. - person BeeNag; 28.04.2016
comment
Потом, когда именно? Мой ответ выше будет проверять, когда пользователь покидает текстовое поле. Разве это не то, что вы ищете? - person Chris; 28.04.2016
comment
onBlur этого не делает. isDisabled никогда не вызывается по какой-то причине, которая, как я полагаю, означает, что событие onBlur не запускается ?? - person BeeNag; 28.04.2016
comment
Это дает мне ошибку Uncaught TypeError: Cannot read property 'email' of undefined - person BeeNag; 28.04.2016
comment
Странно, как это работало раньше. Если вы измените isDisabled() { на isDisabled = () => {, он должен работать. - person Chris; 28.04.2016
comment
Проблема в changeValue, я думаю, может, мне стоит избегать использования nextState? - person BeeNag; 28.04.2016
comment
Да, я исправил это, изменил this.setState ({nextState: nextState}) на this.setState (nextState); и теперь все работает нормально! Спасибо за вашу помощь! - person BeeNag; 28.04.2016

Текущая версия Material-UI не использует опору errorText, но все же есть способ, который вы можете использовать для отображения ошибки и применения проверки к TextField в Material-UI.

Мы используем свойство error (Boolean), чтобы указать, есть ли ошибка. Далее, чтобы отобразить текст ошибки, используйте свойство helperText TextField в Material-UI, просто предоставьте ему текст ошибки, который вы хотите отобразить.

Сделайте это как:

<TextField
  value={this.state.text}
  onChange={event => this.setState({ text: event.target.value })}
  error={text === ""}
  helperText={text === "" ? 'Empty!' : ' '}
/>
person iamakshatjain    schedule 29.08.2019

Самый простой - позвонить form.reportValidity(). form можно получить, позвонив по телефону event.currentTarget.form.

person Loke    schedule 27.08.2018

Эта библиотека, которую я создал, заботится обо всем, что связано с проверкой полей, и поддерживает материалы: компоненты пользовательского интерфейса ...

Чтобы проверить свои поля, вам просто нужно обернуть компонент поля, и все готово ... сэкономив много усилий на ручном управлении состоянием.

<Validation group="myGroup1"
    validators={[
            {
             validator: (val) => !validator.isEmpty(val),
             errorMessage: "Cannot be left empty"
            }, ...
        }]}>
            <TextField value={this.state.value}
                       className={styles.inputStyles}
                       style={{width: "100%"}}
                       onChange={
                        (evt)=>{
                          console.log("you have typed: ", evt.target.value);
                        }


     }/>

person VISHAL DAGA    schedule 18.01.2017
comment
Если вы собираетесь продвигать свои собственные библиотеки, вы должны объявить об этом - см. поведение при переполнении стека - person icc97; 13.03.2017
comment
Я отредактировал ответ, спасибо за модерацию и указание на это. - person VISHAL DAGA; 13.03.2017

Вы можете использовать событие текстового поля onblur. Он срабатывает, когда ввод теряет фокус.

person Yurii Kramarenko    schedule 28.04.2016
comment
Хотя ваше предложение сработает, вероятно, лучше обновлять значение при каждом нажатии клавиши, но вместо этого выполните проверку onblur. - person Chris; 28.04.2016