Selected value in AntD Select - javascript

I'm using the AntD select component, and as you can see in the attached image, when selecting any of its options, AntD select displays "id" rather than "name." Is there a fix for this?
const MyComponent = () => {
const data = [
{
id: "5c83c2d0-e422-4eb6-b2cb-02fe60045e6e"
name: "Item 1"
},
{
id: "1b9175f9-750a-48c1-bbf7-0ff9a2fde7da"
name: "Item 2"
}
];
return (
<Select>
{data.map((item) => (
<Option value={item.id} key={item.id}>{item.name}</Option>
)}
</Select>
);
};

The Ant design <Option> has a prop named label to alter the shown text.
So instead of passing item.name as a child components, pass it as the label prop:
return (
<Select>
{data.map(item => (
<Option value={item.id} key={item.id} label={item.name} />
)}
</Select>
);

Related

Antd Select - how to show different value in the dropdown and Input field

Current UI
Expected Behaviour
How can I do it?
App.tsx
import React from "react";
import "./index.css";
import { Select } from "antd";
const { Option } = Select;
const countryNames = [
{
name: "Japan",
code: "+987"
},
{
name: "aVeryVeryVeryVeryLongCountryName",
code: "+123"
}
];
const handleChange = (value: string) => {
console.log(`selected ${value}`);
};
const App: React.FC = () => (
<>
<Select defaultValue="Japan" onChange={handleChange}>
{countryNames.map((country) => (
<Option key={country.name} value={country.name}>
{`${country.code} ${country.name}`}
</Option>
))}
</Select>
</>
);
export default App;
Codesandbox
https://codesandbox.io/s/basic-usage-antd-5-1-5-forked-mfw8fj?file=/demo.tsx
According to antd document, Select can specify a label value from a Option props with optionLabelProp, which in this use case can get value from country.code.
For extending size of Option based on its content, dropdownMatchSelectWidth can be set false, so that the Option is not limited to the size of Select.
Modified demo on: codesandbox
<Select
defaultValue="Japan"
onChange={handleChange}
// 👇 Specify label prop here
optionLabelProp="label"
// 👇 Set Option to be extendable by content here
dropdownMatchSelectWidth={false}
>
{countryNames.map((country) => (
<Option
key={country.name}
value={country.name}
// 👇 Give label value for Select here
label={country.code}
>
{`${country.code} ${country.name}`}
</Option>
))}
</Select>

not work `onChange` and not work `setState` in `select` tag. (multiple) in react

I have a select tag containing the optgroup and option tags which is multiple.
When I select the items, the state is not updated and the onChange does not work.
I want the value of the option tag to be transferred to state when the item or items are selected !!!.
const FunctionalComponent = () => {
const [mystate , setMyState] = useState([]);
return(
<div>
<select
onChange={(e) => setMyState(e.target.value) }
className='form-control'
multiple='multiple'
value={mystate}
>
{datas.map((obj) => (
return (
<optgroup key={obj.title} label={obj.title}>
{obj.map((o) => (
<option key={o.id} value={o.id}>{o.name}</option>
))}
</optgroup>
);
))}
</select>
</div>
)
}
export default FunctionalComponent
Thanks to those who help me.
Without knowing how datas is structured it's difficult to write code for it, but based on how I think it's structured here some working code.
Intialiase state as an array.
Have your handler get the selectedOptions, and get each option's value. Add that array to your state.
Here datas is an array objects. Each one has a title, and another array of objects containing the option data. map over the main array, and then map over the options array.
const { useState } = React;
function Example({ datas }) {
const [mystate , setMyState] = useState([]);
function handleChange(e) {
const options = e.target.selectedOptions;
const values = Array.from(options, option => option.value);
setMyState(values);
}
return (
<div>
<select
onChange={handleChange}
className="form-control"
multiple="multiple"
value={mystate}
>{datas.map(obj => {
return (
<optgroup
key={obj.title}
label={obj.title}
>{obj.options.map(obj => {
return (
<option
key={obj.id}
value={obj.id}
>{obj.name}
</option>
);
})}
</optgroup>
);
})}
</select>
</div>
);
}
const datas = [
{
title: 1,
options: [
{ id: 1.1, name: 1.1 },
{ id: 1.2, name: 1.2 },
]
},
{
title: 2,
options: [
{ id: 2.1, name: 2.1 },
{ id: 2.2, name: 2.2 },
]
},
];
ReactDOM.render(
<Example datas={datas} />,
document.getElementById('react')
);
form-control { width: 200px; height: 200px}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

How can I do to show three params when I click on the select using react.js?

I have a select such as :
<Select id='1' list={[...this.state.dictionnary]}/>
where this.state.dictionnary is like this :
state = {
dictionnary: [
{value: "a", name: "ab"},
]}
And the component select is like this :
class Select extends Component {
handleChange()
{
// I would like to show 1, a and ab
// 1 is the id of the select
// a and ab are value and name of
};
render() {
return (
<select onChange={this.handleChange} className="custom-select">{this.props.list.map(option => (
<option key={option.value} value={option.value}>{option.name}</option>))}
</select>
)
}
}
export default Select;
I would like to show some informations using the handleChange() function like the id, name and value.
Could you help me please ?
Thank you very much
You should change the option so the value has the entire object to get it later in the handleChange. Also, to access the same this with the props in the handleChange method you need to use an arrow function:
<select onChange={(e) => this.handleChange} className="custom-select">
{this.props.list.map((option) => (
<option key={option.value} value={option}>
{option.name}
</option>
))}
</select>
By default, the onChange handler gets the event param so you can get the target and the props:
handleChange(event) {
const { value, name } = event.target.value;
console.log(this.props.id, value, name);
}
Adding to #Alavaro answer, you need to split after getting the value to remote ,
handleChange = e => {
const [value, name] = e.target.value.split(',')
console.log({ id: this.props.id, value, name})
}
render() {
return (
<select onChange={this.handleChange} className="custom-select">
{this.props.list.map((option, index) => (
<option key={option.value} value={[option.value, option.name]} >
{ option.name }
</option>
))}
</select>
);
}
}

Update Select Option list based on other Select field selection ant design

<Form
layout="vertical"
size="medium"
className="test-form"
requiredMark={false}
onFinish={onFinish}
>
<Form.Item
name="companyId"
label="Company/Customer"
rules={[{ required: true, message: "Please select Company!"}]}
>
<Select
onChange={this.handleSelectCompanyOnchange}
style={{ width: "50%" }}
name="companyId"
>
{users.map((user, index) => {
return (
<Option key={index} value={user.companyID}>
{user.companyName}
</Option>
);
})}
</Select>
</Form.Item>
<Form.Item
label="Products"
name="products"
rules={[{ required: true, message: "Please select Products!"}]}
>
<Select mode="multiple" allowClear style={{ width: "70%" }}>
{products.map((product, index) => {
if (this.state.companyId == product.companyId) {
return (
<Option key={index} value={product.id}>
{product.productName}
</Option>
);
}
})}
</Select>
</Form.Item>
</Form>
I am trying to achieve Options in Products Select element changes according to the Company Select onChange selection.
I have specified onChange in Select and calling this.handleSelectCompanyOnchange. In which I get selected companyId.
In this.state.companyId I had set companyId manually which I will remove.
I am really new to ant design and not able to figure out how to update the Products list once Company is selected.
Here, users and products are json as below.
users:
[{
companyID: 2
companyName: "TEST1"
},{
companyID: 7
companyName: "TEST2"
}]
products:
[{
companyId: 2
id: 1
productName: "TESTProduct1"
},{
companyId: 7
productName: "TESTProduct2"
id: 2
},{
companyId: 7
id: 3
productName: "TESTProduct3"
},{
companyId: 7
id: 4
productName: "TESTProduct4"
}]
However, I have tried getValueFromEvent but not able to achieve this. I am using Ant design Form and Select for this. Also I did referred to https://github.com/ant-design/ant-design/issues/4862 and how to get field value on change for FormItem in antd
Here is what you need to achieve it.
Use onValuesChange prop of the Form. This is the best place to perform setState when it comes to antd Form field changes, not on Select or Input onChange.
<Form onValuesChange={handleFormValuesChange}>
...
</Form>
A form instance (hook). This is optional in your case, but this is useful on setting and getting form values. See more here about it.
const [form] = Form.useForm();
<Form form={form} onValuesChange={handleFormValuesChange}>
...
</Form>
This is the product options render looks like, a combination of map and filter where selectedCompanyId comes from state. Take note that don't use index as key if the fixed length of the list is unknown, the react will confuse on this and you will get some logical error. Use some unique id.
<Form.Item label="Products" name="product">
<Select>
{products
.filter((product) => product.companyId === selectedCompanyId)
.map((product) => (
<Option key={product.id} value={product.id}>
{product.productName}
</Option>
))}
</Select>
</Form.Item>
And here is the handleFormValuesChange
const handleFormValuesChange = (changedValues) => {
const formFieldName = Object.keys(changedValues)[0];
if (formFieldName === "company") {
setSelectedCompanyId(changedValues[formFieldName]); // perform setState here
form.setFieldsValue({product: undefined}) //reset product selection
}
};
Here is the complete working code in react hooks:
the idea here is that you only need to watch the value change in the state.
For example, your select should "watch" a value of state and then you can easily update the state via its own setState method of React. Inside of an onChange event, you can simply just do something with our state.
<Select
value={state.productId}
onChange={e => {// Do something}}
>
{...}
<Select/>
Below is my example code how did I update the day every time I reselect week selection. Hopefully that this can help you.
import { Divider, Select } from 'antd';
import React, { useState } from 'react';
export function Example(): JSX.Element {
const [state, setState] = useState<{week: number, day: number}>({
day: 1,
week: 1
});
const weeks = [1,2,3,4];
const days = [1,2,3,4,5];
return <>
<Select
value={state.week}
onChange={(value) => setState({ week: value, day: 1})}
>
{
weeks.map(week => {
return <Select.Option
key={week}
value={week}
>
{week}
</Select.Option>;
})
}
</Select>
<Divider/>
<Select
value={state.day}
onChange={(value) => setState({...state, day: value})}
>
{
days.map(day => {
return <Select.Option
key={day}
value={day}
>
{day}
</Select.Option>;
})
}
</Select>
</>;
}
Lets say you want to update your option list based on data you get from backend;
note:categories is an array object. From this array you take out label and value for each option, see below:
const newOptions = categories.map((item, index) => {
return {
label: item.name,
value: item._id,
};
});
Then use newOptions inside your form like that:
<Form.Item label="anyName" name="anyName">
<Select style={{ width: 220 }} onChange={ handleChange } options={ newOptions } />
</Form.Item>

Ant Design reset select

I have 2 <Select>'s. The values in the second are dependant on the selection made on the first. When I change the selected item in the first, the available options on the second update. But if I already have a selection made on the second, that option remains selected even if it isn't supposed to be available based on a change to the first select.
How can I reset the second select to have nothing selected when a change is made to the first select?
First Select:
<FormItem {...formTailLayout}>
<FormTitle>Operation</FormTitle>
{getFieldDecorator('Operation', {
rules: [
{
required: true
}
]
})(
<Select
showSearch
placeholder="Select an option"
onChange={this.handleOperationChange}
>
{operations.map(operation => (
<Option value={operation.operation_id}>
{operation.operation_name}
</Option>
))}
</Select>
)}
</FormItem>
Second Select:
<FormItem {...formTailLayout}>
<FormTitle>Metric</FormTitle>
{getFieldDecorator('Metric', {
rules: [
{
required: true
}
]
})(
<Select
showSearch
placeholder="Select an operation first"
onChange={this.handleMetricChange}
>
{matrics
.filter(
metric => metric.operation_fk === operation_fk
)
.map(metric => (
<Option value={metric.metric_name}>
{metric.metric_name}
</Option>
))}
</Select>
)}
</FormItem>
You need to take a look at Coordinated Controls example mentioned on ant-design page. You can simply use setFieldsValue in your first onChange method to set the value of second select field.
handleOperationChange = () => {
this.props.form.setFieldsValue({
Metric: undefined
})
}
I have created a sandbox demo.
In antd, In Class Component, Using Ref, Clear or reset select list value or form item value
add formRef = React.createRef(); just below class component, like:
export default class TestClass extends Component { formRef = React.createRef(); }
add ref={this.formRef} in <Form /> component like this <Form ref={this.formRef}/>
add this line on btn click or in any function you want
this.formRef.current.setFieldsValue({ network: undefined });
Here network in above step is the name of form item
<Form.Item name="network" label="Network"></Form.Item>
Inside handleOperationChange method use resetfileds, this gonna reset your second select box.
this.props.form.resetFields('Metric');
<Select
className="mt-3"
style={{ width: "100%" }}
placeholder="Select your Sub Category"
onChange={handleChangeSubCategory}
disabled={categoryGroup.category === null}
value={categoryGroup.subcategory || undefined}
>
{subCategory.map(item => (
<Option key={item} value={item} label={item}>
<div>
<Avatar style={{ background: "#10899e" }}>
{item[0]}
</Avatar>{" "}
{item}
</div>
</Option>
))}
</Select>
If functional component is used, then we can use Form:
const [form] = Form.useForm()
and it is possible to clear value like this:
const someMethodToClearCurrentSelection = () => {
// ... the code is omitted for the brevity
form.setFieldsValue({ fooProduct: undefined })
}
and our control looks like this:
<Form form={form} name="basic" onFinish={onFinish} layout="vertical">
<Form.Item
key="fooProduct"
name="fooProduct"
label="Some product"
className={s.fooContainer}
rules={[
{
required: true,
message: `Field 'Some produc' is required`,
},
]}
>
<Select
showSearch
optionFilterProp="children"
filterOption={(input, option) =>
option?.children.toLowerCase().includes(input.toLowerCase())
}
allowClear
onChange={handleMarkClick}
>
{products.map((option) => (
<Option key={option.id} value={option.id}>
{option.name}
</Option>
))}
</Select>
</Form.Item>
Read more in antd docs here and examples while migrating from v3 to v4
You can make use of the useEffect() hook.
Define a useForm() custom hook fir your form.
Example: const [form] = Form.useForm();`
Wrap your 1st and 2nd select boxes inside the form and use <Form.Item> to define the input on the form. And whenever the first select's input is changed, clear the 2nd select values in useEffect() hook.
Example:
useEffect(() => {
form.setFieldsValue({
marketplace: [] //2nd select name
});
}, [selectedRegion]); //first select's value
This work perfect for me.

Categories

Resources