Change each individual element style based on condition - javascript

I am trying to change the background color of select element based on which option user selects. I have created this example https://codepen.io/lordKappa/pen/YzrEWXd and here the color changes but it also changes for all select elements not just for the one we changed.
const [selectState, setSelectState] = useState("To-do");
const [taskID, setTaskID] = useState();
function handleDropdownChange(e) {
var taskID = e.currentTarget.getAttribute("data-index");
setTaskID(taskID);
setSelectState(e.target.value);
}
if (selectState === "To-do") {
selectStyle = {
backgroundColor: "red",
};
} else if (selectState === "Done") {
selectStyle = {
backgroundColor: "green",
};
} else {
selectStyle = {
backgroundColor: "yellow",
};
}
return (
<div className="box">
<div>
{elementList.map((task) => (
<div key={task.id}>
<h1>{task.info}</h1>
<select
onChange={handleDropdownChange}
data-index={task.id}
style={selectStyle}
>
<option value="To-do">To-do</option>
<option value="Done">Done</option>
<option value="In progress">In progress</option>
</select>
</div>
))}
</div>
</div>
);
};

The color changes an all dropdowns in the code-pen you provided because they all rely on the same piece of state. You either need to make the state for each dropdown be independent of each other, or separate the dropdown into its own component.

You should create a state for tasks
const [tasks, setTasks] = useState([
{ id: 0, info: "Task 1", status: 'TODO' },
{ id: 1, info: "Task 2", status: 'TODO' },
{ id: 2, info: "Task 3", status: 'TODO' }
]);
Then, everytime you change the selectbox, update status inside tasks state
function handleDropdownChange(e) {
var taskID = e.currentTarget.getAttribute("data-index");
setTasks(tasks.map(task => {
if (taskID !== task.id) return task;
task.status = e.target.value
return task
}));
}
Finally, when rendering tasks we only need to check the task's status and change style
{elementList.map((task) => {
// put your condition here ....
return (
<div key={task.id}>
<h1>{task.info}</h1>
<select
onChange={handleDropdownChange}
data-index={task.id}
style={selectStyle}
>
<option value="To-do">To-do</option>
<option value="Done">Done</option>
<option value="In progress">In progress</option>
</select>
</div>
)
})}

Related

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 do I add select options from an object

I am trying to create a dropdown list based on a object I have. I can't think of a way to do it that's not completely convoluted and the solutions I have come up with don't work either. I'm new to react and stackoverflow so I am not sure if just asking for advice is seen as okay. Forgive me if it's not. I am building it with React. Is there a way to do this that I am missing. Again sorry if you are not supposed to ask for help here
I have created the component as follows
const HardwearForm = ({isActive, Products, outputObj, setOutputObj}) => {
const handleSelect = e => {
let newParentNode = e.target;
let selectedNumber = newParentNode.options.selectedIndex;
let choice = newParentNode.options[selectedNumber].value;
setOutputObj(outputObj[newParentNode.id] = choice);
console.log(outputObj)
}
useEffect(() => {
let parentNode = document.getElementById("make");
Object.keys(Products[isActive]["hardwear"]).forEach(key => {
let newOption = document.createElement('option');
newOption.value = key;
newOption.innerText = key;
parentNode.appendChild(newOption);
})
},[isActive, Products]);
return (
<div>
<select name="make" className="hardwear" id="make" onChange={handleSelect}>
<option value="*">Manufacturer</option>
</select>
<select name="model" className="hardwear" id="model"></select>
{isActive === "handset"|| isActive==="tablet"?
<>
<select name="storage" className="hardwear" id="storage""></select></>:""}
{isActive === "handset"|| isActive==="tablet" ||isActive=== "watch"?
<>
<select name="color" className="hardwear"></select></>:""}
{isActive === "handset"|| isActive==="watch"?
<>
)
The basic idea is I have a menu with a few buttons. Those buttons update the isActive state, which then causes the useEffect to run and populate the first select with the options. That works fine. I've then set it up so once a selection in the first dropdown is chosen it fires the handleSelect function, which does the same thing for the next select. I've set up a empty object to store all the options. setOutputObj(outputObj[newParentNode.id] = choice); ands a key value pair to that object. The problem is, if you then try and change the selected option it errors out "TypeError: Cannot create property 'make' on string 'Huawei'".
Here is an example of the date structure I am using.
"Fairphone": {
"3+": {
"color": ["Black"],
"storage": ["64GB"],
}
},
"Doro": {
"8050": {
"color": ["Black"],
"storage": ["16GB"],
}
},
"Mobiwire": {
"Smart N12": {
"color": ["Dark Metallic Blue"],
"storage": ["16GB"],
}
},
I'm a bit confused about your data structure and what you are trying to achieve, but in general, to dynamically set options of a select input from an object I think it's better to use array.map rather than to try to modify the DOM directly.
For example:
https://codesandbox.io/s/compassionate-buck-8sir5?file=/src/App.js
import { useState } from "react";
import "./styles.css";
const productsByManufacturers = {
"Manufacturer 1": ["product 1", "product 2", "product 3"],
"Manufacturer 2": ["product 4", "product 5"]
};
export default function App() {
const [manufacturer, setManufacturer] = useState("");
return (
<div className="App" style={{ display: "flex", flexDirection: "column" }}>
<label>Select Manufacturer:</label>
<select
value={manufacturer}
onChange={(e) => setManufacturer(e.target.value)}
>
<option value="" disabled>
Select a manufacturer
</option>
{Object.keys(productsByManufacturers).map((manufacturer) => (
<option value={manufacturer}>{manufacturer}</option>
))}
</select>
{manufacturer !== "" && (
<div
style={{ marginTop: 20, display: "flex", flexDirection: "column" }}
>
<label>Select Product:</label>
<select>
{productsByManufacturers[manufacturer].map((product) => (
<option value={product}>{product}</option>
))}
</select>
</div>
)}
</div>
);
}

How can I force the "select" to return to "Choose..." after submit form in React?

How can I force the "select" to return to "Choose..." after submit form?
<select name="activated" className="form-control" as="select" onChange={handleInputChange}>
<option value={values.activated} selected>Choose...</option>
<option value="Activated">Activated</option>
<option value="Deactivated">Deactivated</option>
</select>
I think I have to use the blur or focus method. Some idea?
import Select from 'react-select';
export class Test extends Component {
this.setState = {
selection: 0,
};
onSelectChange = (e) => {
this.setState({ selection: e.value });
}
onSubmit = (e) => {
e.preventDefault();
const { selection } = this.state;
// Post request logic comes here
// Reset Select component to original default state
this.setState({selection: 0});
}
render() {
const options = [
{ label: 'Choose something', value: 0 },
{ label: 'Item 1', value: 1 },
{ label: 'Item 2', value: 2 },
];
return (
<form onSubmit={this.onSubmit}>
<Select
options={options}
value={this.state.selection}
onChange={this.onSelectChange}
/>
//submit button here
</form>
);
Use value prop instead of defaultValue and manage it through state.On Submit, reset that state to initial value i.e 0.
I found a simpler solution than Tayyab's answer:
Adding this code to my handleSubmit function:
document.getElementById("myId").selectedIndex = 0

Geting key value of the dropdown list in reactjs

I'm trying to get the 'key' value of my dynamic dropdown list as follows:
searchSubmit(e){
const s = e.target.value;
alert(s);
}
my dropdown list is as follows:
<select
className="textboxstyle"
onChange={this.searchSubmit}
>
<option key='-1'>Select Brand</option>
<option key='0'>ALL</option>
{optionItems}
</select>
And my dynamic drop-down is populated as follows,
let brands = this.state.brands;
let optionItems = brands.map((brand) =>
<option key={brand.id}>{brand.name}</option>
);
But when I select option, alert display the name of the selected value, not the key. How to get the 'key' value?
Thanks
The key prop is used by React to differentiate between all the elements in an array. If you want value to be the id of the brand, you can use it as value as well as key.
Example
class App extends React.Component {
state = {
brands: [{ id: 1, name: "Foo" }, { id: 2, name: "Bar" }]
};
searchSubmit = e => {
const { value } = e.target;
alert(value);
};
render() {
const { brands } = this.state;
return (
<select onChange={this.searchSubmit}>
<option value="-1">Select Brand</option>
<option value="0">ALL</option>
{brands.map(brand => (
<option value={brand.id} key={brand.id}>
{brand.name}
</option>
))}
</select>
);
}
}
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>

Show object's value text depending on select option

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>

Categories

Resources