Konstantin
Konstantin

Reputation: 51

Using custom class with getFieldDecorator (React, Ant Design)

Everything is ok if I use Ant Design TreeSelect component in form like this:

<Form.Item>
    {getFieldDecorator('geo_objects_value', {
        rules: [{
            required: true,
            message: 'Warning msg'
        }],
    })(
        <TreeSelect
            treeData={treeGeoObjects}
            treeNodeFilterProp={'title'}
            treeCheckable={true}
            allowClear
            showCheckedStrategy={SHOW_PARENT}
            dropdownStyle={{maxHeight: 500, overflow: 'auto'}}
        />
    )}
</Form.Item>

But if I try to use a custom class with the Ant Design Tree component, it will give a warning message: that means the value has not been received.

My custom class:

class Demo extends React.Component {
    constructor(props) {
        super(props);
        this.treeData = props.treeData;
        this.state = {
            expandedKeys: [],
            autoExpandParent: true,
            value: [],
        };
    }

    onExpand = expandedKeys => {
        this.setState({
            expandedKeys,
            autoExpandParent: false,
        });
    };

    onCheck = value => {
        this.setState({value});
        this.props.value = value;
        console.log('onCheck', this.props.value);
    };

    renderTreeNodes = data =>
        data.map(item => {
            if (item.children) {
                return (
                    <TreeNode title={item.title} key={item.key} dataRef={item}>
                        {this.renderTreeNodes(item.children)}
                    </TreeNode>
                );
            }
            return <TreeNode key={item.key} {...item} />;
        });

    render() {
        return (
            <Tree
                checkable
                onExpand={this.onExpand}
                expandedKeys={this.state.expandedKeys}
                autoExpandParent={this.state.autoExpandParent}
                onCheck={this.onCheck}
                checkedKeys={this.state.value}
            >
                {this.renderTreeNodes(this.treeData)}
            </Tree>
        );
    }
}

Using custom class inside the form:

<Form.Item>
    {getFieldDecorator('geo_objects_value', {
        rules: [{
            required: true,
            message: 'Warning msg'
        }],
    })(
        <Demo treeData={treeGeoObjects}/>
    )}
</Form.Item>

What am I doing wrong? Why can't getFieldDecorator get the value from my class? Please help!

Upvotes: 5

Views: 2868

Answers (2)

Dr.Flink
Dr.Flink

Reputation: 572

  1. Create a Component (or PureComponent).
  2. Make sure the controlled value has the same name as the valuePropName.
  3. Create a function that is triggered by onChange. This function will not only update the controlled value, but it will also trigger the controlled onChange handler.
class MyInput extends React.PureComponent {
  constructor(props) {
    super(props);
    const value = props.value || {};
    this.state = {
      // Same name as valuePropName in getFieldDecorator ('value' is default):
      // https://ant.design/components/form/?locale=en-US#getFieldDecorator(id,-options)-parameters
      value,
      // ...
    };
  }

  handleChange = (value) => {
    this.setState({ value });
    const { onChange } = this.props;
    if (onChange) {
      // This will provide the form with changes
      onChange({ ...this.state, ...{ value } });
    }
  }

  render() {
    const { value } = this.state;
    return (
      <Input
        value={value}
        onChange={this.handleChange}
      />
    );
  }
}

Upvotes: 2

Dennis Vash
Dennis Vash

Reputation: 53894

After initializing a custom component with getFieldDecorator, the Form can't control it as it does with default antd components.

In this case, the developer needs to use the injected callbacks and manually control the state.

You need to use this.props.onChange which injected with getFieldDecorator, please read the docs carefully.

After wrapped by getFieldDecorator, value (or other property defined by valuePropName) onChange (or other property defined by trigger) props will be added to form controls, the flow of form data will be handled by Form.

Upvotes: 4

Related Questions