Changes are made in all selections, instead of the one I choose - javascript

Changes are made in all selections, instead of the one I choose. When I check the checkbox in one selection, all the others change. Changing How can I change that?
applications should change the name to the name of the marked checkbox in each selected selection. However, it changes in all the selections I have.
const handleSelect = (e,id) => {
let newValue = [1];
if (e.target.value.length) {
newValue = e.target.value.filter((item) => {
return item > 1;
});
}
const finalString = newValue
.reduce((acumulatedFinal, pass) => {
return acumulatedFinal + ", " + exportOptionNames[pass - 1];
}, "")
.replace(",", "")
.trim();
setSelectedSelections(finalString.length ? finalString : "Export Option");
setExportOption(newValue);
};
<FormControl }>
<Select onClick={(e)=> e.stopPropagation()}
labelId="label"
id="select"
value={exportOption}
multiple
onChange={(e) => handleSelect (e, item.id)}
key={item.id}
renderValue={() => {
return selectedOptionNames;
}}
input={<BootstrapInput />}
>
<MenuItem value={1} disabled>
Export Report
</MenuItem>
<MenuItem value={2}>
<Checkbox checked={exportOption.includes(2)} />
<ListItemText>{exportOptionNames[1]}</ListItemText>
</MenuItem>
<MenuItem value={3}>
<Checkbox checked={exportOption.includes(3)} />
<ListItemText>{exportOptionNames[2]}</ListItemText>
</MenuItem>
<MenuItem value={4}>
<Checkbox checked={exportOption.includes(4)} />
<ListItemText>{exportOptionNames[3]}</ListItemText>
</MenuItem>
</Select>

Related

How do I create dynamic select fields?

I have these 2 fields size and design in which the user can add more of these 2 fields as many times as they want.
Example:
I selected M for the size. It does show in the console:
Additionally, why is it rendering two of size and design at the first load of the screen? Also, add
And now selecting a design:
It will remove the value that was previously selected in the size field.
And in the console, the value of size has been replaced with design2
codesandbox link: https://codesandbox.io/s/form-1-ls6rx?file=/demo.js
import React, { useState, useEffect } from "react";
import Box from "#mui/material/Box";
import InputLabel from "#mui/material/InputLabel";
import MenuItem from "#mui/material/MenuItem";
import FormControl from "#mui/material/FormControl";
import Select from "#mui/material/Select";
import { TextField, Button } from "#mui/material";
export default function BasicSelect() {
const [prod, setProd] = useState("");
const [qty, setQty] = useState(0);
const [design, setDesign] = useState("");
const [sizeList, setSizeList] = useState([{ size: "", design: "" }]);
const handleChange = (event) => {
setProd(event.target.value);
};
const handleSubmit = async (e) => {
e.preventDefault();
console.log(prod, qty, sizeList, design);
};
//helper method
const handleAdd = () => {
setSizeList([...sizeList, { size: "", design: "" }]);
};
const handleRemove = (index) => {
const list = [...sizeList];
list.splice(index, 1);
setSizeList(list);
};
const handleSizeChange = (e, index) => {
const { value } = e.target;
setSizeList((prev) =>
Object.assign([...prev], {
[index]: { size: value }
})
);
};
useEffect(() => {
console.log(sizeList);
}, [sizeList]);
return (
<Box sx={{ minWidth: 120 }}>
<form onSubmit={handleSubmit}>
<FormControl fullWidth>
<InputLabel id="demo-simple-select-label">Product</InputLabel>
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
value={prod}
label="Product"
onChange={handleChange}
>
<MenuItem value="Item1">Item1</MenuItem>
<MenuItem value="Item2">Item2</MenuItem>
<MenuItem value="Item3">Item3</MenuItem>
</Select>
</FormControl>
<br />
<br />
<br />
<br />
{sizeList.map((singleSize, index) => (
<div key={index}>
<FormControl fullWidth>
<InputLabel id="demo-simple-select-label">Size</InputLabel>
<Select
labelId="demo-simple-select-label"
id="size"
value={singleSize.size}
label="Product"
onChange={(e) => handleSizeChange(e, index)}
>
<MenuItem value="S">Small</MenuItem>
<MenuItem value="M">Medium</MenuItem>
<MenuItem value="L">Large</MenuItem>
</Select>
</FormControl>
<FormControl fullWidth>
<InputLabel id="demo-simple-select-label">
Choose Design
</InputLabel>
<Select
labelId="demo-simple-select-label"
id="design"
value={singleSize.design}
label="Product"
onChange={(e) => handleSizeChange(e, index)}
>
<MenuItem value="Design1">Design1</MenuItem>
<MenuItem value="Design2">Design2</MenuItem>
<MenuItem value="Design3">Design3</MenuItem>
</Select>
</FormControl>
<br />
<br />
{sizeList.length > 1 && (
<Button
onClick={() => handleRemove(index)}
variant="contained"
color="secondary"
>
Remove{" "}
</Button>
)}
<br />
<br />
{sizeList.length - 1 === index && (
<Button variant="contained" onClick={handleAdd}>
{" "}
Add Quantity
</Button>
)}
</div>
))}
<br />
<br />
<br />
<br />
<Button type="submit">Submit </Button>
</form>
<Button>Add more Product </Button>
</Box>
);
}
You are using the same handler that is supposed to handle and update states for both the design and size, also there lies a problem in how you are updating the state using Object.assign, this is also leading to additional warnings in the console regarding the value passed, the issue is most likely due to the event conflict.
To put things in place, simply use different handlers to handle updates of different object attributes. A simple solution is to create a new array, make the necessary updates and set the new array to be the updated state, I tested this and it works as expected.
const handleSizeChange = (e, index) => {
const { value } = e.target;
console.log(value)
const arr = [...sizeList] //Shallow copy the existing state
arr[index].size = value //Update the size to the selected size
setSizeList([...arr]); //Set the updated array to be the new state
};
Add a new handler for updating the design value.
const handleDesignChange = (e,index)=>{
const { value } = e.target;
console.log(value)
const arr = [...sizeList]
arr[index].design = value
// console.log(arr)
setSizeList([...arr]);
}
Alternatively, you could club both the handlers into a single handler by adding conditional checks.

React Material-UI Multiselect with checkbox ccannot select all

I am trying to use Material UI multiselect with checkboxes. So far, i am able to make multiple selects and get the values but i am unable to render the actual names of selected values or get all selected values. Any leads to a new approach i can use or useful links to help get the ids of all selected values in my array will be appreciated.
I created a sandbox that has a mock of my data from an api as well here : sandbox
My select looks like this :
const [selected, setSelected] = useState([]);
const isAllSelected =
options.length > 0 && selected.length === options.length;
const handleChange = (event) => {
console.log("vals", event.target);
const value = event.target.value;
if (value[value.length - 1] === "all") {
setSelected(selected.length === options.length ? [] : options.title);
return;
}
setSelected(value);
console.log("values", selected);
};
<FormControl className={classes.formControl}>
<InputLabel id="mutiple-select-label">Multiple Select</InputLabel>
<Select
labelId="mutiple-select-label"
multiple
variant="outlined"
value={selected}
onChange={handleChange}
renderValue={(selected) => selected}
MenuProps={MenuProps}
>
<MenuItem
value="all"
classes={{
root: isAllSelected ? classes.selectedAll : ""
}}
>
<ListItemIcon>
<Checkbox
classes={{ indeterminate: classes.indeterminateColor }}
checked={isAllSelected}
indeterminate={
selected.length > 0 && selected.length < options.length
}
/>
</ListItemIcon>
<ListItemText
classes={{ primary: classes.selectAllText }}
primary="Select All"
/>
</MenuItem>
{options.map((option) => (
<MenuItem key={option.id} value={option.id}>
<ListItemIcon>
<Checkbox checked={selected.includes(option.id)} />
</ListItemIcon>
<ListItemText primary={option.title} />
</MenuItem>
))}
</Select>
<p>{selected}</p>
</FormControl>
I did a few fix in your code so it works, in this sandbox:
To display some text in your menu, you are supposed to display the text in the component ListItemText:
<ListItemText>{option}</ListItemText>
An other thing is that you cannot access selected directly, since it is a state, so it is set asynchronously. To solve this, you can simply access it like this:
selected?.length
This way, even if selected is still undefined, it will not throw any errors

React.js MaterialUI: How to bind the value of a materiaUI select dropdown with the corrispective list item value?

I have a list of users and a Select dropdown from material UI with some values. I am able to console.log the values of the select but how can I know to which user in the List they refer to?
<List>
{userList.map((user:any) => (
<ListItem key={user.key}>
<ListItemAvatar>
<Avatar>
<PersonIcon />
</Avatar>
</ListItemAvatar>
<ListItemText primary={user.name} />
<Select
value={userValue}
onChange={handleChange}
>
{dropdownvalues.map(
(g: { value: string}) => (
<MenuItem key={g.value} value={g.value}>
{g.value}
</MenuItem>
)
)}
</Select>
</ListItem>
))}
</List>
const handleChange=(e:any,index:any) => {
console.log(e.target.value)//here I am able to console log just the value how can I bind the user too given the fact that this funciton doesnt accept another parameter
}
Just add index as value as it is uniquely identifiable in the following code -
{dropdownvalues.map(
(g: { value: string},index:number) => (
<MenuItem key={g.value} value={index}>
{g.value}
</MenuItem>
)
)}
After that just access your selected user as -
const handleChange = (e:any) => {
const selectedInd = e.target.value;
console.log('index->',selectedInd);
console.log(dropdownvalues[e.target.value]);
}
Simplest way is to extend your handleChange function and call like this:
// ...
onChange={(evt) => handleChange(user)}
// ... And then extend the function:
const handleChange=(user:any) => {
console.log(user)
}

Is there some way where I can set a conditional statement for the values of selection?

I have these order status of 'confirmed','on the way' and 'delivered'. How can I set the value for these status to match the values that I have in the select options?
Confirmed - 10
On the way - 20
Delivered - 30
In this scenario, if the status was "On the way" then the previous status will be disabled. So I thought, maybe I could set the status of confirmed to 10 and such..
const Orders = () => {
const [status, setStatus] = useState("");
const [value, setValue] = useState();
const handleChange = (e) => setValue(e.target.value);
return (
<div>
<form onSubmit={handleSubmit}>
<FormControl>
<Select onChange={handleChange} value={value}>
<MenuItem value={10} disabled={value > 10}>
Confirmed
</MenuItem>
<MenuItem value={20} disabled={value > 20}>
On the way
</MenuItem>
<MenuItem value={30} disabled={value > 30}>
On the way (Delayed)
</MenuItem>
<MenuItem value={40} disabled={value > 40}>
Delivered
</MenuItem>
</Select>
</FormControl>
<Button type="submit">Submit</Button>
</form>
</div>
);
};
From what I can understand of your question you want to limit the available options of the Select component based on a dynamic status value.
You can instead disable the options based on the status value. For this you will need to "map" a status to a value that easily matches the option values used by the Select. For simplicity we'll use your 10, 20, 30, and 40 values.
const statusMap = {
Confirmed: 10,
"On the way": 20,
"On the way (Delayed)": 30,
Delivered: 40,
};
Orders - consumes a status prop and uses that for the disabled attribute for options.
const Orders = ({ status }) => {
const [value, setValue] = useState(0);
const handleChange = (e) => setValue(e.target.value);
const handleSubmit = (e) => {
e.preventDefault();
setValue(0);
};
return (
<div>
<form onSubmit={handleSubmit}>
<FormControl>
<Select onChange={handleChange} value={value}>
<MenuItem value={10} disabled={status > 10}>
Confirmed
</MenuItem>
<MenuItem value={20} disabled={status > 20}>
On the way
</MenuItem>
<MenuItem value={30} disabled={status > 30}>
On the way (Delayed)
</MenuItem>
<MenuItem value={40} disabled={status > 40}>
Delivered
</MenuItem>
</Select>
</FormControl>
<Button type="submit">Submit</Button>
</form>
</div>
);
};
Usage
<Orders status={statusMap[statusValueFromAPI]} />

Why onChnage is not a function when a functionalities is migrated to a component for better readability

I'm trying to migrate a specific functionality to a component so I can have better readability in my file.
The functionality is this
display: (filterList, onChange, index, column) => {
const optionValues = preparedSites.reduce((acc, val) => {
const exists = acc.find(
country => country.code === val[3].code,
);
if (!exists) acc.push(val[3]);
return acc;
}, []);
return (
<FormControl>
<InputLabel htmlFor="select-multiple-chip">
Country
</InputLabel>
<Select
value={filterList[index]}
renderValue={selected => selected.join(' ')}
onChange={event => {
onChange([event.target.value], index, column);
}}
>
{optionValues.map(item => (
<MenuItem key={item.code} value={item.code}>
<Flag siteCountry={item} />
<ListItemText primary={item.code} />
</MenuItem>
))}
</Select>
</FormControl>
);
},
What I want to get is that
display: (filterList, onChange, index, column) => <Compnent filterList={filterList} onChange={onChange} index={index} column={column} />
I tried to make it like this but getting onChange is not a function
const Component = (filterList, onChange, index, column) => {
const optionValues = preparedSites.reduce((acc, val) => {
const exists = acc.find(country => country.code === val[3].code);
if (!exists) acc.push(val[3]);
return acc;
}, []);
return (
<FormControl>
<InputLabel htmlFor="select-multiple-chip">Country</InputLabel>
<Select
value={filterList[index]}
renderValue={selected => selected.join(' ')}
onChange={event => {
onChange([event.target.value], index, column);
}}
>
{optionValues.map(item => (
<MenuItem key={item.code} value={item.code}>
<Flag siteCountry={item} />
<ListItemText primary={item.code} />
</MenuItem>
))}
</Select>
</FormControl>
);
};
I would like to understand what wrong.
I decided to answer my own question as was a simple issue.
Probably do tiring of last pre-Christmas urgency deliveries :(
I forgot to add {} in my component:
Before
const Component = (filterList, onChange, index, column) => {}
After
const Component = ({filterList, onChange, index, column}) => {}
Now all seems to work correctly.

Categories

Resources