I have a Select from react-select
that's multi option, I want an option placed on top op the others that invert selected options to unselected and vice versa.
And when this 'Invert selection' option is selected don't show in grey into selected options preview.
I know that there's a second parameter to onChange
prop that means the action, where I can see which option were selected or unelected, but I don't know how to properly manage the options.
How my Select component looks like:
Code:
<Select
placeholder="Selecionar..."
defaultValue={issuesTypes.results.map(
(iT) =>
selectedCategoryOptions.includes(iT.id) && {
value: iT.id,
label: iT.title,
}
)}
isMulti
closeMenuOnSelect={false}
hideSelectedOptions={false}
onChange={(options, a) => {
if (Array.isArray(options)) {
setSelectedCategoryOptions(options.map((opt) => opt.value));
}
}}
options={(() => {
let aux = [];
issuesTypes.results.map((iT) => {
if (iT.isActive) {
aux.push({
value: iT.id,
label: iT.title,
});
}
});
return aux;
})()}
components={{
Option: DefaultInputOption,
}}
/>;
const DefaultInputOption = ({
getStyles,
Icon,
isDisabled,
isFocused,
isSelected,
children,
innerProps,
...rest
}) => {
const [isActive, setIsActive] = useState(false);
const onMouseDown = () => setIsActive(true);
const onMouseUp = () => setIsActive(false);
const onMouseLeave = () => setIsActive(false);
// styles
let bg = "transparent";
if (isFocused) bg = "#eee";
if (isActive) bg = "#B2D4FF";
const style = {
alignItems: "center",
backgroundColor: bg,
color: "inherit",
display: "flex ",
};
// prop assignment
const props = {
...innerProps,
onMouseDown,
onMouseUp,
onMouseLeave,
style,
};
return (
<components.Option
{...rest}
isDisabled={isDisabled}
isFocused={isFocused}
isSelected={isSelected}
getStyles={getStyles}
innerProps={props}
>
<input type="checkbox" checked={isSelected} onChange={() => {}} />
{children}
</components.Option>
);
};
Found the solution. Inside components prop you can overwrite some components, just like I did with Option in the above question, so I created a MenuList wich is the dropdown menu and passed to components:
components={{
Option: DefaultInputOption,
MenuList: MenuList,
}}
MenuList:
const MenuList = (props) => {
return (
<components.MenuList {...props}>
<div
style={{
padding: "8px 12px",
cursor: "pointer",
borderBottom: "1px solid rgb(220, 220, 220)",
}}
onClick={async (e) => {
for (let i = 0; i < props.children.length; i++) {
let child = props.children[i];
await child.props.selectOption(child.props.data);
}
}}
>
Invert selection
</div>
{props.children}
</components.MenuList>
);
};
As you can see it has a div with inner text "Invert Selection" and the magic is in the onClick
function, calling selectOption
will trigger the UI selection on inputs inside DefaultInputOption
and the onChange
inside <Select />
.