Defenestrate
Defenestrate

Reputation: 463

Why won't custom input controls validation properly in Ant Design forms?

I'm using Ant Design and I have the following trouble with Forms.

I have a custom component which wraps an antd AutoComplete with the code required to fetch autocomplete suggestions remotely:

const ProductComplete = () => {
    const [value, setValue] = React.useState('')
    const [options, setOptions] = React.useState([])
    const onSearch = searchText => {
        fetchProductsFromServer(searchText)
            .then(options => options.map(o => ({value: o})))
            .then(options => setOptions(options))
    }
    const onChange = data => {
        setValue(data)
    }
    return (
        <AutoComplete
            value={value}
            options={options}
            onSearch={onSearch}
            onChange={onChange}
        />
    )
}

but when I use it in an antd Form :

return (
    <Form
        {...formLayout}
        ref={this.formRef}
    >
        <Form.Item
            name={'product'}
            label={'Product'}
            rules={[{
                required: true
            }]}
        >
            <ProductComplete/>
        </Form.Item>
    </Form>

when I trigger validation externally thus : let fieldsValue = await this.formRef.current.validateFields() the form behaves as if there's nothing in the field and signals the user that the field is required as per the validation rule specified (even when there is text in the AutoComplete)

However, if I were to wire the AutoComplete directly into the component holding the Form, rather than have it packaged as it's own component (as above), it works fine though !

return (
    <Form
        {...formLayout}
        ref={this.formRef}
    >
        <Form.Item
            name={'product'}
            label={'Product'}
            rules={[{
                required: true
            }]}
        >
            <AutoComplete
                value={this.state.product}
                options={this.state.products}
                onSearch={(searchText) => this.onSearchProducts(searchText)}
                onChange={(value) => this.onChange(value)}
            />
        </Form.Item>
    </Form>

Any ideas why this may be ?

Cheers!

Upvotes: 4

Views: 4027

Answers (1)

Defenestrate
Defenestrate

Reputation: 463

Nevermind I figured it out!

I somehow hadn't noticed the https://ant.design/components/form/#components-form-demo-customized-form-controls section on the Ant Design website.

I simply needed to pass the custom component a controlled value property and onChange event thus:

const ProductComplete = ({value = '', onChange}) => {
    const [products, setProducts] = React.useState([])
    const onSearch = searchText => {
        fakeFetch(searchText)
            .then(options => options.map(o => ({value: o})))
            .then(options => setProducts(options))
    }
    const handleChange = (value) => {
        if (onChange) {
            onChange(value)
        }
    }
    return (
        <AutoComplete
            value={value}
            options={products}
            onSearch={onSearch}
            onChange={handleChange}
        />
    )
}

Works fine now. Pretty obvious really .

Cheers

Upvotes: 10

Related Questions