I have multiselect dropdown items with checkboxes in my react app, what I am trying to achieve is if I checked any three items, then dropdown should display maximum items selected and if I unchecked anyone of them, it should display back the drop down box with items. Somehow it doesn't work, could someone please advise.
CodeSanbox link
https://codesandbox.io/s/musing-sun-swvj6y?file=/src/App.js
import { useState } from "react";
import Multiselect from "multiselect-react-dropdown";
import "./styles.css";
export default function App() {
const options = [
{ key: "Apple", email: "[email protected]", id: 1 },
{ key: "Orange", email: "[email protected]", id: 2 },
{ key: "Mango", email: "[email protected]", id: 3 },
{ key: "Grapes", email: "[email protected]", id: 4 }
];
const [option, setOption] = useState([]);
const [selectedOption, setSelectedOption] = useState([]);
const [maxOptions, setMaxOptions] = useState(0);
const handleTypeSelect = (e, i) => {
const copy = [...selectedOption];
copy.push(e[3 - maxOptions]);
setSelectedOption(copy);
setMaxOptions((prevState) => prevState - 1);
};
const handleTypeRemove = (e) => {
const copy = [...selectedOption];
let index = copy.indexOf(e);
copy.splice(index, 1);
setSelectedOption(copy);
setMaxOptions((prevState) => prevState 1);
};
options.forEach((option) => {
option.displayValue = option.key "\t" option.email;
});
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<Multiselect
onSelect={(e) => handleTypeSelect(e, selectedOption.length)}
onRemove={handleTypeRemove}
options={selectedOption.length 1 === maxOptions ? [] : options}
// options={!showOptions ? [] : option}
displayValue="displayValue"
showCheckbox={true}
emptyRecordMsg={"Maximum fruits selected !"}
/>
</div>
);
}
CodePudding user response:
The library doesn't support manually selecting/deselecting the options. Reference
There is one hack that you can do. You can play around with key
. Use the selectedItems
as key
and then it will re-mount the component whenever the selectedItems
changes.
Note that this hack is not the recommended way to do "React".
You update the options based on the size of the selected options
const maxSelectableItems = 3;
const options = [
{ key: "Apple", email: "[email protected]", id: 1 },
{ key: "Orange", email: "[email protected]", id: 2 },
{ key: "Mango", email: "[email protected]", id: 3 },
{ key: "Grapes", email: "[email protected]", id: 4 }
];
<Multiselect
// This will re-mount your component whenever
// selected items changes
key={selectedItems}
onSelect={handleSelection}
onRemove={handleRemove}
// This will set the pre-selected values on re-mount
selectedValues={selectedItems}
options={
selectedItems.length === maxSelectableItems
? []
: options.map((o) => ({
...o,
displayValue: `${o.key}\t${o.email}`
}))
}
displayValue="displayValue"
showCheckbox
emptyRecordMsg={"Maximum fruits selected !"}
/>
And, your handleSelection
and handleRemove
will look like this:
const [selectedItems, setSelectedItems] = useState([]);
const handleSelection = (selectedItems) => {
setSelectedItems(selectedItems.slice(0, maxSelectableItems));
};
const handleRemove = (selectedItems) => {
setSelectedItems(selectedItems);
};
One issue with this is that since it re-mounts the entire multi-select component, when you select/remove an item, the input will lose focus. So, you will have to manually give focus to the input after selection/removal.
const focusOnInput = () => {
setTimeout(() => {
// You can use a better selector (this is just a generic input selector)
document.querySelector("input").focus();
// Adding some delay to allow the component to re-mount
}, 10);
};
And then, use this in your selection/removal handlers
const handleSelection = (selectedItems) => {
setSelectedItems(selectedItems.slice(0, maxSelectableItems));
focusOnInput()
};
const handleRemove = (selectedItems) => {
setSelectedItems(selectedItems);
focusOnInput()
};
Here is a link to a working sandbox
CodePudding user response:
import { useState } from "react";
import Multiselect from "multiselect-react-dropdown";
import "./styles.css";
export default function App() {
const options = [
{ key: "Apple", email: "[email protected]", id: 1 },
{ key: "Orange", email: "[email protected]", id: 2 },
{ key: "Mango", email: "[email protected]", id: 3 },
{ key: "Grapes", email: "[email protected]", id: 4 }
];
const [option, setOption] = useState([]);
const [selectedOption, setSelectedOption] = useState([]);
const [maxOptions, setMaxOptions] = useState(0);
options.forEach((option) => {
option.displayValue = option.key "\t" option.email;
});
return (
<div className="App">
<h1>Hello CodeSandbox2</h1>
<Multiselect
options={options}
displayValue="displayValue"
showCheckbox={true}
selectionLimit={3}
emptyRecordMsg={"Maximum fruits selected !"}
/>
</div>
);
}