Reputation: 376
I'm having trouble with antd forms in regard to Select
input. I have two Select
inputs and I need the second input to "reset" to the first option when the first input changes value.
I need to keep track of each Select
value with React.useState
because —in my real code— those values are used to make a request to a backend and re-populate other Select
inputs but the first one, and each Select
have a different amount of options, thus is desirable that they get "reset" to the first option.
How can I achieve what I'm looking for?
Upvotes: 0
Views: 939
Reputation: 5539
If you add Select
into the Form
and Form.Item
and set a name for Form.Item
, the Select
is completely controlled by the Form
. You need to use the Form's api to control the Select
or simply remove the name
import React from "react";
import ReactDOM from "react-dom";
import { Select, Form } from "antd";
import "antd/dist/antd.css";
const fieldA = [{ value: 1, text: "Hello" }, { value: 2, text: "World" }];
const fieldB = [{ value: 1, text: "A" }, { value: 2, text: "B" }];
const App = () => {
const [myvalues, setMyvalues] = React.useState({ valueA: 1, valueB: 1 });
const setFieldA = (value: number) => {
setMyvalues({ valueA: value, valueB: 1 });
form.setFieldsValue({ valueA: value, valueB: 1 });
};
const setFieldB = (value: number) => {
setMyvalues({ ...myvalues, valueB: value });
form.setFieldsValue({ ...myvalues, valueB: value });
};
const [form] = Form.useForm();
return (
<Form layout="vertical" form={form} initialValues={myvalues}>
<Form.Item name="valueA" label="Field A" shouldUpdate>
<Select value={myvalues.valueA} onChange={setFieldA}>
{fieldA.map(field => (
<Select.Option value={field.value}>{field.text}</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item name="valueB" label="Field B" shouldUpdate>
<Select value={myvalues.valueB} onChange={setFieldB}>
{fieldB.map(field => (
<Select.Option value={field.value}>{field.text}</Select.Option>
))}
</Select>
</Form.Item>
<div>
Field A "real" value: {myvalues.valueA}.<br />
Field B "real" value: {myvalues.valueB}
</div>
</Form>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
You can check here CodeSandBox. Hope it helps
Upvotes: 2
Reputation: 15186
Since you decide to control the input field with value and onChange,
You don't need the Form name, remove it.
Then set the first hander, check if the value changed to decide whether set the second to default or not.
import React from "react";
import ReactDOM from "react-dom";
import { Select, Form } from "antd";
import "antd/dist/antd.css";
const fieldA = [{ value: 1, text: "Hello" }, { value: 2, text: "World" }];
const fieldB = [{ value: 1, text: "A" }, { value: 2, text: "B" }];
const App = () => {
const [valueA, setValueA] = React.useState(null);
const [valueB, setValueB] = React.useState(null);
const setFieldA = (value: number) => {
if (valueA !== value) {
setValueB(null);
}
setValueA(value);
};
const setFieldB = (value: number) => {
setValueB(value);
};
return (
<Form layout="vertical">
<Form.Item label="Field A">
<Select value={valueA} onChange={setFieldA}>
{fieldA.map(field => (
<Select.Option value={field.value}>{field.text}</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item label="Field B">
<Select value={valueB} onChange={setFieldB}>
{fieldB.map(field => (
<Select.Option value={field.value}>{field.text}</Select.Option>
))}
</Select>
</Form.Item>
<div>
Field A "real" value: {valueA}
<br />
Field B "real" value: {valueB}
</div>
</Form>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Upvotes: 2