Select and Checkbox components-> multiple options but with a maximum choice? - reactjs

I want to use the Select and Checkbox components with MUI with the multiple props , so the users can pick multiples options. However, I want , that they are limited to 3 options maximum . I can't find this props to set the min and maximum choice . Is it possible ?! I would be really happy if so .
Here is my code :
const languages = [
"Anglais",
"Arabe",
"Espagnol",
"Italien",
"Français",
"Mandarin",
"Hebreu",
"Russe",
"Portugais",
"Autre",
];
<FormControl className={classes.formControl}>
<Select
multiple={true}
value={language}
onChange={handleChange}
MenuProps={MenuProps}
>
{languages.map((language) => (
<MenuItem key={language} value={language}>
{language}
</MenuItem>
))}
</Select>
</FormControl>
Thanks !

<Select
multiple={true}
value={language}
onChange={handleChange}
MenuProps={MenuProps}
>
{languages.map((lang) => (
<MenuItem
key={lang}
disabled={language.length >= 3 && !language.includes(lang)}
value={lang}
>
{language}
</MenuItem>
))}
</Select>
Had to change the map parameter since it's name is the same as the state variable.
This will disable any non-selected items when state (language) has 3 or more items.

This should help you make it for yourself.
const languages = [
"Anglais",
"Arabe",
"Espagnol",
"Italien",
"Français",
"Mandarin",
"Hebreu",
"Russe",
"Portugais",
"Autre",
];
const App = () => {
const [selectedItem , setSelectedItem] = React.useState([]);
const selectHandler = (e) => {
const select = e.currentTarget.value;
if(selectedItem.length <3)
setSelectedItem((prev)=> [...prev,select])
}
return (
<div>
<p>{selectedItem.map((item)=>item+"-")}</p>
<select onChange={selectHandler}>
{languages.map((language) => (
<option key={language} value={language}>
{language}
</option>
))}
</select>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("react"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
In your case, just pass selectedItem as a value to the Select component solve the problem.

Related

onChange event won't fire in .map function React

I cannot get this onChange event to fire? The goal is to render multiple options from a drop down, from some data I have, then console log "hello" when any of the options is clicked...
It doesn't seem to want to let me use onChange or onClick events in my rendered option elements. If i can simply console log first , then i can figure out everything else. I only posted the necessary code but I can post the rest if needed!
const SlideData = [
{
title: "Slide 0",
},
{
title: "Slide 1",
},
{
title: "Slide 2",
},
];
export default SlideData;
let options = SlideData.map((item, index) => (
<option
key={index}
value={index}
onChange={() => {
console.log("hello");
}}
>
{item.title}
</option>
));
<select className={styles.select} onChange={goto}>
<option>--Select--</option>
{options}
</select>
option tag doesn't support onChange. You can use onClick instead.
onClick={() => {
console.log("hello");
}}
goal was to pass the index and console log it technically. so I guess this worked for me
const slideRef = useRef();
const goto = ({ target }) => {
slideRef.current.goTo(parseInt(target.value, 10));
console.log(target.value);
};
const options = SlideData.map((item, index) => (
<option key={index} value={index}>
{item.title}
</option>
));
return (
<div className={styles.container}>
<Slide ref={slideRef} {...properties}>
<div className={styles.slide}>First Slide</div>
<div className={styles.slide}>Second Slide</div>
<div className={styles.slide}>Third Slide</div>
<div className={styles.slide}>Fourth Slide</div>
<div className={styles.slide}>Fifth Slide</div>
</Slide>
<div>
<Button type="button" onClick={back}>
Back
</Button>
<Button type="button" onClick={next}>
Next
</Button>
<select className={styles.select} onChange={goto}>
<option>--Select--</option>
{options}
</select>
</div>
</div>
);

how to pass array values to Formik select

I am using Formik for a bunch of admin console forms that I have in my application. So far I did not have this use case.
My Formik forms use one of 2 custom components, either a Myinputtext(input box) or a MySelect(drop down). I dont have a need for any other components so far. Here is how my Myselect component looks like.
const MySelect = ({ label, ...props }) => {
const [field, meta] = useField(props);
return (
<div>
<label htmlFor={props.id || props.name}>{label}</label>
<select className={props.className} {...field} {...props} />
{meta.touched && meta.error ? (
<div className="error">{meta.error}</div>
) : null}
</div>
);
};
Over in the form I am passing values to this component like this
<MySelect className="select-input" label="Losing Player" name="losingPlayer">
<option value="">Select Losing Player</option>
<option value="player1">{state.Player1Name} </option>
<option value="player2">{state.Player2Name} </option>
All of this works for a few forms I have built so far. In the fourth form now, data coming back from the back end is coming as an array and I am trying to pass the array as input to the myselect component
<MySelect className="select-input" label="Losing Player" name="losingPlayer">
<option value="">Select Losing Player</option>
<option value="player1">{name of array object} </option>
This is failing and not providing the right result.
In the formik official docs it says there is a way to handle array objects like this
<Form>
<Field name="friends[0]" />
<Field name="friends[1]" />
<button type="submit">Submit</button>
</Form>
</Formik>
But my array size can be dynamic and I cannot hardcode, 0,1 like above.
I tried rendering the array inside the select component like this,
<MySelect className="select-input" label="Winning Player" name="winningPlayer">
{props.initialValues.map((player) => {
<option key={player} value={player}> {player} </option> })} </MySelect>
this does not throw any errors. but the drop down is displayed empty.
I am basically hoping to have the names in the array displayed as the dropdown. What is the right solution to tackle this?
This finally worked:-
return (
<div>
<label htmlFor={props.id || props.name}>{label}</label>
{!props.player ? <select className={props.className} {...field} {...props} />
:
<select className={props.className}>
{props.player.map((player) => {
return (
<option key={player} value={player}>
{player}
</option>
)
})}
</select>
}
{meta.touched && meta.error ? (
<div className="error">{meta.error}</div>
) : null}
</div>
You need to map your array and render options inside your select like this:
{options?.map(({ value }) => (
<option key={value} value={value}>
{value}
</option>
))}

How to get the value of custom atttributes in react hooks?

How do I get the value of custom attributes using react hooks?
Here is sample code in code sandbox : demo live
code
import "./styles.css";
import React, { useState } from "react";
export default function App() {
const [value, setValue] = useState("");
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<select
onChange={(e) => {
console.log("value", e.target.value);
console.log("description", e.target.description);
setValue(e.target.value);
}}
name="cars"
id="cars"
>
<option value="volvo" description="hahahahaa">
Volvo
</option>
<option value="saab" description="hehehehehe">
Saab
</option>
<option value="opel" description="hoooooooo">
Opel
</option>
<option value="audi" description="huuuuuuuuuu">
Audi
</option>
</select>
</div>
);
}
I am able to get the value of attribute value but not the custom description.
I get undefined console.log("description", e.target.description);
What is wrong here?
e.target give you the select tag, you can get the option tag and the description like this:
console.log("description", e.target.childNodes[e.target.selectedIndex].getAttribute("description"));
In your example target is the <select> and you would need to traverse to the selected option and get the attribute value.
It really doesn't seem practical to store data in a custom option attribute when you could use a hashmap with values as keys
const Example = () => {
const [desc, setDesc] = React.useState('')
const descriptions = {
volvo:'hahahahaa',
saab:'hehehehehe',
opel:'hoooooooo'
}
const handleChange = (e)=>{
const val = e.target.value,
des = descriptions[val]
console.clear()
console.log("value",val);
console.log("description", des);
setDesc(des)
}
return (
<div>
<div>Description: {desc}</div>
<select
onChange={handleChange}
name="cars"
id="cars"
>
<option value="volvo">
Volvo
</option>
<option value="saab">
Saab
</option>
<option value="opel" >
Opel
</option>
</select>
</div>
);
};
// Render it
ReactDOM.render(
<Example title="Example using Hooks:" />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>

Multiple Dropdown in reactjs

I want to select multiple dropdown values in react js using Dynamic Values.
<Col lg="10">
<select id="facility_id" className="form-control select2" value={this.state.facility_id} onChange={this.handleChange} title="Type Growing system" isMulti>
<option value="0">None</option>
{this.state.facilities.map((faci, key) =>
<option key={key} value={faci.facility_id}>{faci.facility_name}</option>
)}
</select>
react-select is not working for me . Any other options available?
Use element attr multiple instead of isMulti.
Try something like this.
const Select = () => {
const [selections, setSelections] = React.useState(['b', 'c']);
const onSeletionChange = val => {
let sels = [...selections];
if (sels.includes(val)) {
sels = sels.filter(x => x !== val);
} else {
sels.push(val);
}
setSelections(sels);
}
return (
<div>
Multi Select (select again to remove)
<select
id="facility_id"
className="form-control select2"
value={selections}
onChange={(e) => {
console.log(e.target.value);
onSeletionChange(e.target.value);
}}
title="Type Growing system"
multiple
>
<option value="0" key="0">None</option>
{["a", "b", "c"].map((faci, key) => (
<option key={key} value={faci}>
{faci}
</option>
))}
</select>
</div>
);
};
const domContainer = document.querySelector('#app');
ReactDOM.render(<Select />, domContainer);
<script crossorigin src="https://unpkg.com/react#16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.production.min.js"></script>
<div id="app"> </div>

Use image as icon with react-select

I would like to add an image as Icon with react-select. I did all right but I have a problem with the fact that, in react, images are written like this :
<img src={require(...)} />
So I use react-select like this :
const IconOption = (props) => (
<Option {... props}>
<div>
<img src={require(props.data.image)} />
</div>
</Option>
);
And then call for the select box :
render() {
return (
<Select
classNamePrefix="react-select"
placeholder={"Search..."}
onChange={this.handleChange}
components={{ DropdownIndicator: () => null, Option: IconOption }}
options={this.state.options}
openMenuOnClick={false}
styles={customStyle}
/>
);
}
I tried to write :
const IconOption = (props) => (
<Option {... props}>
<div>
{props.data.image}
</div>
</Option>
);
Which gives me :
./css/img/PROFILEPICTURE.jpg
It is exactly what I want to get, the path is correct. If I exactly write :
const IconOption = (props) => (
<Option {... props}>
<div>
<img src="./css/img/PROFILEPICTURE.jpg" />
</div>
</Option>
);
Image is correctly displayed.
If I write the first code, which is the one to get different picture for each item in selectbox, I got an error :
Any solution to not use require function for img in react?
Edit :
I also tried :
const IconOption = (props) =>
(
<Option {... props}>
<div>
<img src={props.data.image} />
{props.data.label}
</div>
</Option>
);
And i got not found images :
You just have to remove the require since your image is not part of the compiled react app:
const IconOption = (props) => (
<Option {... props}>
<div>
<img src={props.data.image} />
</div>
</Option>
);

Resources