Как включить / отключить кнопку при пользовательской проверке с помощью React

У меня простая форма с 3 входами и одной кнопкой.

Кнопка отправки по умолчанию отключена, и каждый вход имеет настраиваемую логику проверки с регулярным выражением.

Как я могу снова включить кнопку, когда все проверки пройдены?

Это моя составляющая:

import React, { Component } from 'react';
import { Input, Upload , Icon, message} from 'antd';
import Form from '../../components/uielements/form';
import Checkbox from '../../components/uielements/checkbox';
import Button from '../../components/uielements/button';
import Notification from '../../components/notification';
import { adalApiFetch } from '../../adalConfig';

const FormItem = Form.Item;

class RegisterTenantForm extends Component {
    constructor(props) {
        super(props);
        this.state = {TenantId: '', TenantUrl: '', CertificatePassword: '', confirmDirty: false, loading: false, buttondisabled: true };
        this.handleChangeTenantUrl = this.handleChangeTenantUrl.bind(this);
        this.handleChangeCertificatePassword = this.handleChangeCertificatePassword.bind(this);
        this.handleChangeTenantId= this.handleChangeTenantId.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
        this.handleupload = this.handleupload.bind(this);
        this.handleTenantIdValidation = this.handleTenantIdValidation.bind(this);
        this.handleTenantAdminUrl = this.handleTenantAdminUrl.bind(this);

    };

    handleChangeTenantUrl(event){
        this.setState({TenantUrl: event.target.value});
    }

    handleChangeCertificatePassword(event){
        this.setState({CertificatePassword: event.target.value});
    }

    handleChangeTenantId(event){
        this.setState({TenantId: event.target.value});
    }

    beforeUpload(file) {
        const isJPG = file.type === 'image/jpeg';
        if (!isJPG) {
          message.error('You can only upload JPG file!');
        }
    }

    handleupload(info){
        //let files = e.target.files;
        if (info.file.status === 'uploading') {
            this.setState({ loading: true });
            return;
        }

        if (info.file.status === 'done') {
            this.setState({ loading: false });
            this.setState({ 'selectedFile': info.file });
        }

    }

    handleTenantIdValidation(rule, value, callback){
        const form = this.props.form;
        var re = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
        if (!form.getFieldValue('tenantid').match(re)) {
            callback('Tenant id is not correctly formated id');
        } 
        else {
            callback();
        }
    }

    handleTenantAdminUrl(rule, value, callback){
        const form = this.props.form;
        var re = /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/i;
        if (!form.getFieldValue('tenantadminurl').match(re)) {
            callback('Tenant Url is not correctly formated id');
        } 
        else {
            callback();
        }
    }


    handleSubmit(e){
        e.preventDefault();
        this.props.form.validateFieldsAndScroll((err, values) => {
            if (!err) {
                /*Notification(
                'success',
                'Received values of form',
                JSON.stringify(values)
                );*/

                let data = new FormData();
                //Append files to form data
                data.append("model", JSON.stringify({ "TenantId": this.state.TenantId, "TenantUrl": this.state.TenantUrl, "CertificatePassword": this.state.CertificatePassword }));
                //data.append("model", {"TenantId": this.state.TenantId, "TenantUrl": this.state.TenantUrl, "TenantPassword": this.state.TenantPassword });

                let files = this.state.selectedFile;
                for (let i = 0; i < files.length; i++) {
                  data.append("file", files[i], files[i].name);
                }

                const options = {
                  method: 'put',
                  body: data,
                  config: {
                    headers: {
                      'Content-Type': 'multipart/form-data'
                    }
                  }
                };

                adalApiFetch(fetch, "/Tenant", options)
                  .then(response => response.json())
                  .then(responseJson => {
                    if (!this.isCancelled) {
                      this.setState({ data: responseJson });
                    }
                  })
                  .catch(error => {
                    console.error(error);
                });
            }
        });      
    }



    render() {
        const uploadButton = (
            <div>
                <Icon type={this.state.loading ? 'loading' : 'plus'} />
                <div className="ant-upload-text">Upload</div>
            </div>
        );

        const { getFieldDecorator } = this.props.form;

        const formItemLayout = {
        labelCol: {
            xs: { span: 24 },
            sm: { span: 6 },
        },
        wrapperCol: {
            xs: { span: 24 },
            sm: { span: 14 },
        },
        };
        const tailFormItemLayout = {
        wrapperCol: {
            xs: {
            span: 24,
            offset: 0,
            },
            sm: {
            span: 14,
            offset: 6,
            },
        },
        };
        return (
            <Form onSubmit={this.handleSubmit}>
                <FormItem {...formItemLayout} label="Tenant Id" hasFeedback>
                {getFieldDecorator('tenantid', {
                    rules: [
                    {
                        required: true,
                        message: 'Please input your tenant id',
                    },
                    {
                        validator: this.handleTenantIdValidation
                    }],
                })(<Input name="tenantid" id="tenantid" onChange={this.handleChangeTenantId}/>)}
                </FormItem>
                <FormItem {...formItemLayout} label="Certificate Password" hasFeedback>
                {getFieldDecorator('certificatepassword', {
                    rules: [
                    {
                        required: true,
                        message: 'Please input your password!',
                    }
                    ],
                })(<Input type="password" name="certificatepassword" id="certificatepassword" onChange={this.handleChangeCertificatePassword}/>)}
                </FormItem>
                <FormItem {...formItemLayout} label="Tenant admin url" hasFeedback>
                {getFieldDecorator('tenantadminurl', {
                    rules: [
                    {
                        required: true,
                        message: 'Please input your tenant admin url!',
                    },
                    {
                        validator: this.handleTenantAdminUrl
                    }],
                })(<Input name="tenantadminurl" id="tenantadminurl"  onChange={this.handleChangeTenantUrl} />)}
                </FormItem>
                <FormItem {...formItemLayout} label="Certificate File">
                    <Upload  onChange={this.handleupload} beforeUpload={this.beforeUpload}>

                        <Button >
                            <Icon type="upload" /> Click to Upload
                        </Button>
                    </Upload>

                </FormItem>
                <FormItem {...tailFormItemLayout}>
                    <Button type="primary" htmlType="submit" disabled={this.state.buttondisabled}>
                        Register tenant
                    </Button>
                </FormItem>
            </Form>
        );
    }
}

const WrappedRegisterTenantForm = Form.create()(RegisterTenantForm);
export default WrappedRegisterTenantForm;

Обновлять:

Ответ должен быть предоставлен с использованием Ant Design API


person Luis Valencia    schedule 24.07.2018    source источник


Ответы (4)


В каждом блоке валидатора if установите состояние buttonDisabledState на true и в каждом операторе else установите его на false.

Когда все поля будут проверены, для вашего состояния отключения btn будет установлено значение false.

person Gurpreet Singh    schedule 24.07.2018
comment
это не так, как только я помещаю действительный идентификатор в первое поле, а второе поле все еще пусто, тогда кнопка активируется. - person Luis Valencia; 24.07.2018
comment
Загляните в этот раздел, надеюсь, он решит вашу проблему ant.design/components/form/ # Form.Item - person Gurpreet Singh; 25.07.2018

Отключенное значение вашей кнопки - это логическое значение, которое зависит от состояния вашего компонента.

Итак, что вам нужно сделать, это установить для этого логического значения false, когда все проверки пройдены:

this.setState({buttonDisabled: false})
person Guillaume    schedule 24.07.2018
comment
все проверки выполняются разными методами, так что это сбивает с толку, просьба дополнить ответ моим кодом. может это проще, чем я думаю - person Luis Valencia; 24.07.2018
comment
api правил проверки: ant.design/components/form/?locale= en-US # Validation-Rules - person Luis Valencia; 24.07.2018

Добавьте в свое состояние логическое значение, то есть isValidated, которое по умолчанию равно false, и вы измените его на true, когда все проверки пройдут. Вы вроде как уже делаете это с state.buttondisabled - просто setState это false, когда все проверки пройдут.

person LMulvey    schedule 24.07.2018
comment
но есть 3 разных проверки для 3 разных методов, я немного смущен - person Luis Valencia; 24.07.2018
comment
Похоже, что валидаторы передаются как ссылка на getFieldDecorator, которая передается как опора для компонента Form. Дальнейшая отладка без остального кода затруднена. Вы захотите взглянуть на реализацию callback() в getFieldDecorator и увидеть, что она делает. - person LMulvey; 24.07.2018
comment
api правил проверки: ant.design/components/form/?locale= en-US # Validation-Rules - person Luis Valencia; 24.07.2018
comment
К сожалению, я не знаком с конкретными реализациями этих библиотек. Что вы могли сделать, так это добавить несколько дополнительных переменных состояния, чтобы определить, прошел ли каждый конкретный валидатор, а затем обновить их индивидуально в каждой функции валидатора. Пример: this.state = {TenantId: '', TenantUrl: '', CertificatePassword: '', confirmDirty: false, loading: false, buttondisabled: true, tenantIdValidated: false };, а затем в handleTenantIdValidation, где callback() вызывается без аргументов: this.setState({tenantIdValidated: true}); - person LMulvey; 24.07.2018
comment
Это похоже на тонну обезьяньих отлов, и я бы не рекомендовал это. Я уверен, что AntDesign имеет правильную реализацию для обработки отключения / включения кнопки отправки. Я рекомендую вам повторно задать вопрос с помощью тега AntDesign или прочитать их документацию по сравнению с ответом, который я предложил. - person LMulvey; 24.07.2018

Загляните в этот раздел, надеюсь, он решит вашу проблему https://ant.design/components/form/#Form.Item

person Gurpreet Singh    schedule 24.07.2018