How to dynamically set a required rule to the Form.Item validation

poltorin picture poltorin · Nov 13, 2019 · Viewed 10.3k times · Source

I have a list of parameters that may be checked or not. Its correspondent fields are enabled/disabled in dependence of checkbox state. So I want to enable and validate field if parameter is checked, and disable field and turn off validation rule while checkbox is unchecked. But I can't switch required rule to false while toggling checkbox.

As you see the registrations parameter is unchecked but the field still have a validation..

Here is how I've done it:

<Row key={index} gutter={8}>
  <Col span={6} offset={4}>
    <Form.Item help="">
      <Checkbox
        checked={attribute.isActive}
        disabled={isViewMode}
        onChange={this.handleChangeAttributeActive(attribute.eventId)}
        value={attribute.name}
      >
        {attribute.name}
      </Checkbox>
    </Form.Item>
  </Col>
  <Col span={8}>
    <Form.Item help="">
      {getFieldDecorator(`${attribute.name}`, {
        initialValue: attribute.attributeSendName,
        rules: [{ required: attribute.isActive }],
      })(
        <Input
          disabled={isViewMode || !attribute.isActive}
        />
      )}
    </Form.Item>
  </Col>
</Row>

attributes is an array of parameters that stores in component state. Checkbox handler just switch to opposite isActive property

Can you please help? Thank

Answer

blueseal picture blueseal · Nov 14, 2019

validateFields() accepts two arguments. You should provide {force: true} as the second argument to validate the field properly.

handleChangeAttributeActive = e => {
    this.setState(
      prevState => ({
        ...prevState,
        attribute: { ...prevState.attribute, isActive: e.target.checked }
      }),
      () => {
        this.props.form.validateFields([e.target.value], { force: true });
      }
    );
  };

validation in antd

validateFields validates the specified fields and get their values and errors. If you don't specify the parameter of fieldNames, you will validate all fields.

import { Row, Col, Checkbox, Form, Input } from "antd";

class App extends Component {
  state = {
    attribute: {
      name: "name",
      isActive: true,
      eventId: 1,
      attributeSendName: "enter your name"
    },
    isViewMode: false
  };

  handleChangeAttributeActive = e => {
    this.setState(
      prevState => ({
        ...prevState,
        attribute: { ...prevState.attribute, isActive: e.target.checked }
      }),
      () => {
        this.props.form.validateFields([e.target.value], { force: true });
      }
    );
  };

  render() {
    const { getFieldDecorator } = this.props.form;
    const { attribute, isViewMode } = this.state;
    const index = 0;
    return (
      <div className="App">
        <Row key={index} gutter={8}>
          <Col span={6} offset={4}>
            <Form.Item help="">
              <Checkbox
                checked={attribute.isActive}
                disabled={isViewMode}
                onChange={this.handleChangeAttributeActive}
                value={attribute.name}
              >
                {attribute.name}
              </Checkbox>
            </Form.Item>
          </Col>
          <Col span={8}>
            <Form.Item help="">
              {getFieldDecorator(`${attribute.name}`, {
                message: attribute.attributeSendName,
                rules: [{ required: attribute.isActive }]
              })(<Input />)}
            </Form.Item>
          </Col>
        </Row>
      </div>
    );
  }
}

const WrappedApp = Form.create()(App);

const rootElement = document.getElementById("root");
ReactDOM.render(<WrappedApp />, rootElement);

Change this code as per your need.