Multiple Dropdown in reactjs - 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>

Related

Characters filter by property value in React.js

I'm a trying to build an app based on Rick and Morty api.
I want to filter characters by species.
I've created separate components for each species value
For example:
Human.js
export const Human = ({ match }) => {
const { species } = match.params;
const [characterFilters, setCharacterFilters] = useState([]);
useEffect(() => {
try {
fetch('https://rickandmortyapi.com/api/character?species=human')
.then((res) => res.json())
.then((res) => setCharacterFilters(res))
.catch((err) => console.log(err));
} catch (e) {
console.log(e);
}
}, []);
const { name, image } = characterFilters;
return (
<div>
<h2>Name: {name}</h2>
<div>
<img alt={name} src={image}></img>
</div>
</div>
);
};
In the characters file I've set the conditions based on select propery chosen
Characters.js
export const Characters = () => {
const [characters, setCharacters] = useState();
useEffect(() => {
try {
fetch(CHARACTERS_PAGE_URL)
.then((res) => res.json())
.then(({ results }) => {
if (results && Array.isArray(results)) {
setCharacters(results);
}
})
.catch((err) => console.log(err));
} catch (e) {
console.log(e);
}
}, []);
const handleSpeciesChange = (e) => {
console.log("[e.target.value]", e.target.value);
switch (e.target.value) {
case "human":
return <Human />;
break;
case "alien":
return <Alien />;
break;
case "unknown":
return <Unknown />;
break;
default:
return;
}
};
const handleStatusChange = (e) => {
switch (e.target.value) {
case "alive":
return <Human />;
break;
case "dead":
return <Alien />;
break;
case "unknown":
return <Unknown />;
break;
default:
return;
}
};
if (!characters) {
return <Loading />;
}
return (
<div className="p-4 font-mono text-green-500 ">
<div className="flex flex-row">
<div className="m-4 ">
<label>Species</label>
<select name="species" id="species" onChange={handleSpeciesChange}>
<option value="all">all</option>
<option value="human">human</option>
<option value="alien">alien</option>
<option value="unknown">unknown</option>
</select>
</div>
<div className="m-4">
<label>Status</label>
<select name="status" id="status" onChange={handleStatusChange}>
<option value="all">all</option>
<option value="alive">alive</option>
<option value="dead">dead</option>
<option value="unknown">unknown</option>
</select>
</div>
<div className="m-4">
<label>Gender</label>
<select name="gender" id="gender">
<option value="all">all</option>
<option value="female">female</option>
<option value="male">male</option>
<option value="genderless">genderless</option>
<option value="unknown">unknown</option>
</select>
</div>
</div>
<h1 className="text-4xl">Characters</h1>
<Pagination data={characters} pageLimit={5} />
<div className="grid grid-flow-col grid-cols-5 grid-rows-4 gap-4">
{characters.map((character) => (
<div key={character.id}>
<Character character={character} />
</div>
))}
</div>
</div>
);
};
But I'm not getting filtered characters.
I'm new to React.
Please help me to understand, what am I doing wrong here?
Is there a possibility to created a common filter component that I would be able to apply for different properties filters?
You cannot return jsx from a callback
Make filters get stored and only render these values from the array:
export const Characters = () => {
const [characters, setCharacters] = useState();
const [ speciesFilter, setSpeciesFilter ] = useState('');
const [ status, setStatus] = useState('');
useEffect(() => {
try {
fetch(CHARACTERS_PAGE_URL)
.then((res) => res.json())
.then(({ results }) => {
if (results && Array.isArray(results)) {
setCharacters(results);
}
})
.catch((err) => console.log(err));
} catch (e) {
console.log(e);
}
}, []);
const handleSpeciesChange = (e) => {
console.log("[e.target.value]", e.target.value);
setSpeciesFilter(e.target.value)
};
const handleStatusChange = (e) => {
setStatus(e.target.value);
};
if (!characters) {
return <Loading />;
}
let filteredCharacters = characters;
if (speciesFilter) {
filteredCharacters = filteredCharacters.filter(c => c.species === speciesFilter);
}
if (status ) {
filteredCharacters = filteredCharacters.filter(c => c.status === status);
}
return (
<div className="p-4 font-mono text-green-500 ">
<div className="flex flex-row">
<div className="m-4 ">
<label>Species</label>
<select name="species" id="species" onChange={handleSpeciesChange}>
<option value="all">all</option>
<option value="human">human</option>
<option value="alien">alien</option>
<option value="unknown">unknown</option>
</select>
</div>
<div className="m-4">
<label>Status</label>
<select name="status" id="status" onChange={handleStatusChange}>
<option value="all">all</option>
<option value="alive">alive</option>
<option value="dead">dead</option>
<option value="unknown">unknown</option>
</select>
</div>
<div className="m-4">
<label>Gender</label>
<select name="gender" id="gender">
<option value="all">all</option>
<option value="female">female</option>
<option value="male">male</option>
<option value="genderless">genderless</option>
<option value="unknown">unknown</option>
</select>
</div>
</div>
<h1 className="text-4xl">Characters</h1>
<Pagination data={characters} pageLimit={5} />
<div className="grid grid-flow-col grid-cols-5 grid-rows-4 gap-4">
{filteredCharacters.map((character) => (
<div key={character.id}>
<Character character={character} />
</div>
))}
</div>
</div>
);
};
The above example uses a filter which can be improved
what am I doing wrong here?
You are returning JSX from the callback, for example,
onChange={handleStatusChange}
Here you pass the function which will be passed the event for you to handle, the problem is, returning a component from this function doesn't do anything, it doesn't tell React to render the component you returned.
Instead, you can store the value from there in state, and do something accordingly, for example, filter the array using that value
Is there a possibility to created a common filter component that I
would be able to apply for different properties filters?
That can be done, by passing the characters to that component and the filter values
export const FilterCharacters = ({ characters, status, specie }) => {
let filteredCharacters = characters;
if (specie ) {
filteredCharacters = filteredCharacters.filter(c => c.species === specie);
}
if (status ) {
filteredCharacters = filteredCharacters.filter(c => c.status === status);
}
return filteredCharacters.map((character) => (
<div key={character.id}>
<Character character={character} />
</div>
))
}
As for your Human and specific species components, it calls the API for filtered values, but I assume you already got all values initially, so you could only filter from there, if that's not the case, you could make Human more generic by passing the species and status, and querying the API with that values

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>

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

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.

connecting a select tag to a form, and then reseting it at submit

hi guys I'm trying to reset a select tag after the submit using React,I connected the first option to the state which is :
state = {
inputs: [],
tempInput: {
inputType: 'Please select a type'
}
};
so I basically select a type in my form, it updates the tempInput object with the inputType, and then add it to the array of objects,
<div className="formG">
<form className="form-maker" onSubmit={this.handleSubmit}>
<select onChange={this.onSelect}>
<option>{this.state.tempInput.inputType}</option>
<option value="text">text</option>
<option value="color">color</option>
<option value="date">date</option>
<option value="email">email</option>
<option value="tel">tel</option>
<option value="number">number</option>
</select>
<button>Submit</button>
</form>
this is my on select method:
onSelect = ({ target }) => {
const { tempInput } = this.state;
tempInput.inputType = target.value;
this.setState({ tempInput });
};
handleSubmit = e => {
e.preventDefault();
how to do that in handleSubmit? to put the tempInput.inputType to ="Please pick a type"
};
This is an uncontrolled element.
If you want to control the value of an input / select you need to set it via your state:
const values = [
"text", "color", "date", "email", "tel","number"
]
class App extends React.Component {
state = { value: "" };
onSelect = ({target}) => this.setState({value: target.value})
handleSubmit = () => {
console.log('submit with ',this.state.value)
this.setState({value: ''})
}
render() {
const { value } = this.state;
return (
<div>
<select onChange={this.onSelect}>
<option>Select A value</option>
{values.map(val => <option key={val} value={val} selected={val === value}>{val}</option>)}
</select>
<button onClick={this.handleSubmit}>Submit</button>
<div>{`Selectet Value is ${value}`}</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" />
Here is the example without the array:
class App extends React.Component {
state = { value: "" };
onSelect = ({ target }) => this.setState({ value: target.value })
handleSubmit = () => {
console.log('submit with ', this.state.value)
this.setState({ value: '' })
}
render() {
const { value } = this.state;
return (
<div>
<select onChange={this.onSelect}>
<option selected={value === ""} value="">Select A value</option>
<option selected={value === "text"} value="text">text</option>
<option selected={value === "color"} value="color">color</option>
<option selected={value === "date"} value="date">date</option>
<option selected={value === "email"} value="email">email</option>
<option selected={value === "tel"} value="tel">tel</option>
<option selected={value === "number"} value="number">number</option>
</select>
<button onClick={this.handleSubmit}>Submit</button>
<div>{`Selectet Value is ${value}`}</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"/>
Of course there is a lot of repeated code here, in programming there is the "DRY" principle (Do Not Repeat Yourself).
This is why we use loops like Array.prototype.map
in your onSelect function, you're mutate the state object(tempInput.inputType = target.value;), it is not a good practice in react.
if you want your select value controlled by the react state, first you need to bind it's value with react state, which it's called a controlled component, like:
<select onChange={this.onSelect} value={this.state.tempInput.inputType}>

getting input with select

in my react application I wish to change the input to a select tag in my form , how can I do that?
<form className="form-maker" onSubmit={this.handleSubmit}>
Type:
<input name="inputType" type="text" onChange={this.handleChange} />
</form>
in to this:
<select>
<option value="text">text</option>
<option value="color">color</option>
<option value="date">date</option>
<option value="email">email</option>
<option value="tel">tel</option>
<option value="number">number</option>
</select>
The handleChange goes in the <select /> element, similar to the <input />.
Here is a small running example:
class App extends React.Component {
state = { value: "text" };
onSelect = ({target}) => this.setState({value: target.value})
render() {
const { value } = this.state;
return (
<div>
<select onChange={this.onSelect}>
<option value="text">text</option>
<option value="color">color</option>
<option value="date">date</option>
<option value="email">email</option>
<option value="tel">tel</option>
<option value="number">number</option>
</select>
<div>{`Selectet Value is ${value}`}</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 will probably want an array of these values, so it will be easier to render the <options /> and set the selected attribute.
Here is another example, this time with a different default value selected:
const values = [
"text", "color", "date", "email", "tel","number"
]
class App extends React.Component {
state = { value: "date" };
onSelect = ({target}) => this.setState({value: target.value})
render() {
const { value } = this.state;
return (
<div>
<select onChange={this.onSelect}>
{values.map(val => <option key={val} value={val} selected={val === value}>{val}</option>)}
</select>
<div>{`Selectet Value is ${value}`}</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" />

Resources