I am using antd library as part of react application. For select option values are fetched from api and rendered in this format.
<Select
{...propsForSelect}
>
{this.props.data.map(e =>
<Option
key={e.key || e}
value={e.value || e}
title={e.title}
>
{`${e.key} | ${e.value}`}
/Option>
)}
</Select>
Once user selects an option I want to display only the value and not {${e.key} | ${e.value}} value.
{${e.key} | ${e.value}} is displaying in dropdown and when user selects an option need to show e.value alone.
CodeSandbox: https://codesandbox.io/s/tender-feynman-uhtn7
Is this what you are looking for?
https://codesandbox.io/s/headless-river-1n0e3
Basically I just added a selected property to each genre object, and then in the Select component's onSelect() prop, passed a callback function that updates state and toggles the respective genre's selected property to true.
Then, in the UI, I simply check if the selected property is true for each genre and then conditionally render only the display value in that case.
This is what the optionLabelProp is for.
import React from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
import { Select } from 'antd';
const { Option } = Select;
class App extends React.Component {
state = {
genres: [{"key": 1000, "value": "1", "display": "Action"},
{"key": 1001, "value": "2", "display": "Adventure"},
{"key": 1002, "value": "3", "display": "Comedy"}]
};
render() {
return (
<div className="container">
<Select
style={{width:"50%"}}
optionLabelProp="value"
>
{this.state.genres.map(e =>
<Option
key={e.key}
value={e.value}
>
{`${e.display} | ${e.value}`}
</Option>
)}
</Select>
</div>
);
}
}
ReactDOM.render(
<App />,
document.getElementById('container'),
);
class App extends React.Component {
state = {
genres: [
{ key: 1000, value: "1", display: "Action" },
{ key: 1001, value: "2", display: "Adventure" },
{ key: 1002, value: "3", display: "Comedy" }
],
selected: '' // A default value can be used here e.g., first element in genres
};
handleChange = key => {
this.setState({ selected: this.state.genres.find((object) => object.key === Number(key)).value });
};
render() {
return (
<div className="container">
<Select value={this.state.selected} onChange={this.handleChange} style={{ width: "50%" }}>
{this.state.genres.map(e => (
<Option key={e.key}>
{`${e.display} | ${e.value}`}
</Option>
))}
</Select>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("container"));
Related
I am still new in React and MUI, so please spare my life. I am learning to build Multiple Select Options with Checkboxes and I have populated the Dropdown Options from an Array.
I also have set up the initial/default state options. The initial/default state options (Nintendo & XBoX) are showing up in the main Input Select Field but unfortunately not being checked marked in the Dropdown Checkboxes, such as in the screenshot below.
Screenshot 1
What I'm trying to achieve is to be like this (all the selected options (Nintendo & XBoX) from the default state is showing on the checkboxes at initial page load):
Screenshot 2
This is my Live Demo coding in https://stackblitz.com/edit/react-rahqrq?file=demo.js
I'm confused, I can tick all the other option checkboxes in the dropdown except the default Initial Options from the State. It's unclickable and unchangeable, I have no idea why. Any tips and clues are greatly appreciated, Thanks in advance, please pardon my poor Grammar and Best Regards.
import * as React from 'react';
import OutlinedInput from '#mui/material/OutlinedInput';
import InputLabel from '#mui/material/InputLabel';
import MenuItem from '#mui/material/MenuItem';
import FormControl from '#mui/material/FormControl';
import ListItemText from '#mui/material/ListItemText';
import Select from '#mui/material/Select';
import Checkbox from '#mui/material/Checkbox';
const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
PaperProps: {
style: {
maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
width: 250,
},
},
};
const variants = [
{
id: 3,
name: 'Voucher',
},
{
id: 1,
name: 'Top Up',
},
{
id: 2,
name: 'Game Key',
},
{
id: 12,
name: 'Other',
},
{
id: 11,
name: 'Nintendo',
},
{
id: 10,
name: 'Xbox',
},
];
export default function MultipleSelectCheckmarks() {
const [variantName, setVariantName] = React.useState([{
id: 11,
name: 'Nintendo',
},{
id: 10,
name: 'Xbox'
},]);
const handleChange = (event) => {
const {
target: { value },
} = event;
const preventDuplicate = value.filter((v, i, a) => a.findIndex((t) => t.id === v.id) === i);
setVariantName(
// On autofill we get a the stringified value.
typeof preventDuplicate === 'string' ? preventDuplicate.split(',') : preventDuplicate
);
};
return (
<div>
<FormControl sx={{ m: 1, width: 300 }}>
<InputLabel id="demo-multiple-checkbox-label">Tag</InputLabel>
<Select
labelId="demo-multiple-checkbox-label"
id="demo-multiple-checkbox"
multiple
value={variantName}
onChange={handleChange}
input={<OutlinedInput label="Tag" />}
renderValue={(selected) => selected.map((x) => x.name).join(', ')}
MenuProps={MenuProps}
>
{variants.map((variant) => (
<MenuItem key={variant.id} value={variant}>
<Checkbox checked={variantName.indexOf(variant) > -1} />
<ListItemText primary={variant.name} />
</MenuItem>
))}
</Select>
</FormControl>
</div>
);
}
You need to findIndex of each item in the initial list to make them checked.
Try like below
{
variants.map(variant => (
<MenuItem key={variant.id} value={variant}>
<Checkbox
checked={
variantName.findIndex(item => item.id === variant.id) >= 0
}
/>
<ListItemText primary={variant.name} />
</MenuItem>
));
}
Code sandbox => https://stackblitz.com/edit/react-rahqrq-sd2m2b?file=demo.js
I am having a JSON file in below mentioned format and I want to map the elements to second drop down based on the first drop down value.
Can I achieve it by using this syntax
const toolList = datalist.AssetCategory; -- datalist is the JSON file name <br>
const AIAssets = datalist.SelectedValue; -- SelectedValue is an variable.
--- JSON Data
{
"AssetCategory":
[
{
"toolname" :"Industry"
},
{
"toolname" :"Process"
},
{
"toolname": "Technology"
}
],
"Industry":
[
{
"asset" : "Banking"
},
{
"asset" : "HealthCare"
},
{
"asset" : "Telecom"
},
{
"asset" : "Finance & Banking"
},
{
"asset" : "Insurance"
},
{
"asset" : "Manufacturing"
}
],
"Process":
[
{
"asset" : "Accounts Payable"
},
{
"asset" : "Finance & Accounting"
},
{
"asset" : "Human Resources"
}
],
"Technology":
[
{
"asset" : "Excel"
},
{
"asset" : "SAP S/4HANA"
},
{
"asset" : "GUI"
}
]
}
Here's working example of your problem, though for secondary dropdown it doesn't support dynamic keys you'll have to specify them. But for first one you can have as many dynamic keys as you want.
Complete Demo
You can access the values from first dropdown as follows
import React, { useState } from "react";
import data from "./data.json";
export default function App() {
// Set primary keys here
const primaryOptions = Object.keys(data);
// Option selected from first dropdown, initially set to be empty
const [selectedPrimaryOption, setSelectedPrimaryOption] = useState("");
// Array of secondary selected options
const [secondaryOptions, setSecondaryOptions] = useState([]);
// Change the secondary dropdown when first is changed.
const handleChange = e => {
const value = e.target.value;
setSelectedPrimaryOption(value);
if (value) {
// Accessing keys ['asset', 'toolname'] etc. here
const secondaryData = data[value].map(
v => v["asset"] || v["toolname"] || v
);
setSecondaryOptions(secondaryData);
}
};
return (
<div className="App">
<div>
<label>Primary Select</label>
<select value={selectedPrimaryOption} onChange={handleChange}>
<option value="">Select Option</option>
{primaryOptions.map(option => (
<option value={option} key={option}>
{option}
</option>
))}
</select>
</div>
<div>
<label>Secondary Select</label>
<select>
{secondaryOptions.map(option => (
<option value={option} key={option}>
{option}
</option>
))}
</select>
</div>
</div>
);
}
I am using react-select for my select dropdown. The issue I am having is that there is no empty option to reset the dropdown value if the user changes their mind.
Currently I am taking the options and manually adding an empty string, but I feel there must be something already in the library to handle this? I cannot find anything in the docs.
My code looks like the below, and there is a code sandbox here.
import React from "react";
import Select from "react-select";
const App = () => {
const options = [
{ value: "chocolate", label: "Chocolate" },
{ value: "strawberry", label: "Strawberry" },
{ value: "vanilla", label: "Vanilla" }
];
return <Dropdown options={options} />;
}
const Dropdown = ({ options }) => {
const optionsWithEmptyOption = [{ value: "", label: "" }, ...options];
return <Select options={optionsWithEmptyOption} />;
};
Plase check this out
https://codesandbox.io/s/zow1c?module=/example.js
import React, { Component } from 'react';
import CreatableSelect from 'react-select/creatable';
import { colourOptions } from './docs/data';
export default class CreatableSingle extends Component<*, State> {
handleChange = (newValue: any, actionMeta: any) => {
console.group('Value Changed');
console.log(newValue);
console.log(`action: ${actionMeta.action}`);
console.groupEnd();
};
handleInputChange = (inputValue: any, actionMeta: any) => {
console.group('Input Changed');
console.log(inputValue);
console.log(`action: ${actionMeta.action}`);
console.groupEnd();
};
render() {
return (
<CreatableSelect
isClearable
onChange={this.handleChange}
onInputChange={this.handleInputChange}
options={colourOptions}
/>
);
}
}
Empty Unicode
I add line to options, and write between the apostrophes empty unicode like this: ⠀⠀⠀⠀⠀⠀⠀⠀ .. you can mark it but dont see it.
const options = [
{ value: "", label: "⠀" },
{ value: "chocolate", label: "Chocolate" },
{ value: "strawberry", label: "Strawberry" },
{ value: "vanilla", label: "Vanilla" }
];
And I change this:
return <Select options={options} />;
what about const optionsWithEmptyOption = [{ value: null, label: "Select..." }, ...options];
I'm not really good with explanations, but #NicoHaase is right, so here it goes...
as far as I know, you must give a value to value null (if nothing) or string ... same for the label, #1 because of the user UX and second so react-select knows what to display. But if you really need to leave it in black, and you can try to modify in the styles, in order to have the same height as the other options.
I am using react-select for autocomplete and option related field. When i select the option it passes whole that option object as {value: 'abc', label: 'ABC'} but i wanted only to pass the value as a string not the object. Thus, i used getOptionValue but it is not working as expected.
This is what I have done
<Field
name='status'
component={SearchableText}
placeholder="Search..."
options={status}
styles={styles}
getOptionLabel={option => option.label}
getOptionValue={option => option.value}
/>
I have used both getOptionLabel and getOptionValue but is still passing the selected option in object form instead of just the value as string.
Expected one
status: 'active'
Current behavior
status: { value: 'active', label: 'Active'}
I couldn't find getOptionValue in the docs for react-select, but you could always create an adapter around react-select. i.e. create your own Select component that uses react-select's Select component internally. After doing this it becomes possible to create your own getOptionValue. You can use this to make sure the value is a string.
import React from "react";
import Select from "react-select";
class MySelect extends React.Component {
getSelectValue() {
return this.props.options.find(
option => this.props.getOptionValue(option) === this.props.input.value
);
}
render() {
console.log("value", this.props.input.value);
return (
<Select
value={this.getSelectValue()}
onChange={option => {
this.props.input.onChange(this.props.getOptionValue(option));
}}
options={this.props.options}
/>
);
}
}
MySelect.defaultProps = {
getOptionValue: v => v
};
const MyForm = reduxForm({ form: "MyForm" })(
class extends React.PureComponent {
render() {
return (
<Field
name="myCoolSelect"
component={MySelect}
options={[
{ value: "chocolate", label: "Chocolate" },
{ value: "strawberry", label: "Strawberry" },
{ value: "vanilla", label: "Vanilla" }
]}
getOptionValue={option => option.value}
/>
);
}
}
);
The above is a basic example of how to get this working. You may want to pass other input or meta props to take advantage of other redux-form features. e.g. onBlur, onFocus, etc. You can see it in action here: https://codesandbox.io/s/6wykjnv32n
so I have this issue I am trying to solve, with React.
Let's say I have an object like so:
"options": {
"open": {
"text": "Open (Risky)",
"description": "Filler text for open"
},
"wpa": {
"text": "WPAWPA2PSK (TKIP / AES)",
"description": "Filler text for wpa"
},
"wpa2": {
"text": "WPA2-PSK (AES) (Recommended)",
"description": "Filler text for wpa2"
}
}
And I have it setup that the object's value's "text" is used to populate option values in a select dropdown, like so:
const securityModeOptions = Object.values(securityMode.select.options);
{securityModeOptions.map((mode, index) =>
<option key={index} value={mode.text}>
{mode.text}
</option>
)}
What I would like to do is that whichever option value is selected, it's corresponding "description" is displayed in a div next to it, and the div changes based on whichever option is selected.
Thanks!
You can manage a state of the selected key, then grab the relevant entry from the options object via the key.
Something like this:
const options = {
open: {
text: "Open (Risky)",
description: "Filler text for open"
},
wpa: {
text: "WPAWPA2PSK (TKIP / AES)",
description: "Filler text for wpa"
},
wpa2: {
text: "WPA2-PSK (AES) (Recommended)",
description: "Filler text for wpa2"
}
};
class App extends React.Component {
state = { selectedOptionKey: "" };
onChange = ({ target }) => {
this.setState({ selectedOptionKey: target.value });
};
render() {
const { selectedOptionKey } = this.state;
const description =
options[selectedOptionKey] && options[selectedOptionKey].description;
return (
<div>
<select onChange={this.onChange}>
<option>Choose</option>
{Object.entries(options).map(([key, value]) => (
<option value={key}>{value.text}</option>
))}
</select>
<div>{description}</div>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"/>
You could keep the key of the selected option in state and show the description of this selected option.
Example
const options = {
open: {
text: "Open (Risky)",
description: "Filler text for open"
},
wpa: {
text: "WPAWPA2PSK (TKIP / AES)",
description: "Filler text for wpa"
},
wpa2: {
text: "WPA2-PSK (AES) (Recommended)",
description: "Filler text for wpa2"
}
};
class App extends React.Component {
state = {
options,
selected: Object.keys(options)[0]
};
onChange = event => {
this.setState({ selected: event.target.value });
};
render() {
const { options, selected } = this.state;
return (
<div>
<select onChange={this.onChange}>
{Object.keys(options).map(key => (
<option key={key} value={key}>
{options[key].text}
</option>
))}
</select>
<span>{options[selected].description}</span>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>