如何自定义 Select 以显示以逗号分隔的 selected 选项?反应-select
How to customize Select to display selected options separated by comma? react-select
我尝试从 react-select 库自定义 Select 组件。
我用 span
元素自定义了 multiSelectValue
并在标签中添加了逗号。但它不适用于输入。当下拉列表中的项目 selected 时,它按预期工作。但是,当我尝试为搜索选项输入值时,输入会被聚焦,并且 span
项目向左移动,结果字段变为空。
多个select
export default function App() {
const [values, setValues] = useState([]);
return (
<div className="root">
<Select
styles={styles}
isSearchable
isMulti
getOptionValue={(option) => option["value"]}
options={options}
value={values}
onChange={(options) => {
setValues(() => options);
}}
components={{
MultiValue: CustomMultiValue
}}
/>
</div>
);
}
自定义 selected 值
function CustomMultiValue(props) {
const { getValue, data } = props;
const selectedOptions = getValue();
const currentOptionIdx = selectedOptions.findIndex(
(option) => option.value === data.value
);
return (
<span>
{data.label}
{currentOptionIdx === selectedOptions.length - 1 ? "" : ", "}
</span>
);
}
沙盒项目https://codesandbox.io/s/boring-knuth-kfo1e?file=/src/CustomMultiValue.js
我认为您的代码没有任何问题。也许你应该尝试增加 Select
的宽度,这样你就可以看到所有其他 multi-values 被剪裁在你的 codesandbox 中。
const width = "500px";
const styles = {
control: (provided) => ({
...provided,
width
}),
menu: (provided) => ({
...provided,
width
}),
...
};
我找到了解决办法。
要实现它需要做 2 个操作:
- 在 select 打开时更改 ValueContainer 的溢出样式
- 菜单关闭时向左滚动
当菜单打开时使用 overflow:unset
- 因此输入将在 selected 值的末尾正确显示
当菜单关闭时,使用 overflow:ellipsis
显示第一个 selected 值并需要对它们进行切片
valueContainer: (provided, state) => {
const disableOverflow =
state.selectProps.isSearchable && state.selectProps.menuIsOpen;
return {
whiteSpace: "nowrap",
textOverflow: disableOverflow ? "unset" : "ellipsis",
overflow: "hidden",
flex: "1 1 0%",
position: "relative"
};
},
要向左滚动需要使用自定义 ValueContainer
并将 ref
传递给该容器。检查 menuIsOpen
何时更改为 false
并在那一刻向左滚动。
function CustomMultiValueContainer(props) {
const {
selectProps: { menuIsOpen }
} = props;
const containerRef = useRef(null);
const styles = props.getStyles("valueContainer", props);
useEffect(() => {
if (!menuIsOpen) {
if (containerRef && containerRef.current) {
containerRef.current.scrollLeft = 0;
}
}
}, [menuIsOpen]);
return (
<div ref={containerRef} style={styles}>
{props.children}
</div>
);
}
我尝试从 react-select 库自定义 Select 组件。
我用 span
元素自定义了 multiSelectValue
并在标签中添加了逗号。但它不适用于输入。当下拉列表中的项目 selected 时,它按预期工作。但是,当我尝试为搜索选项输入值时,输入会被聚焦,并且 span
项目向左移动,结果字段变为空。
多个select
export default function App() {
const [values, setValues] = useState([]);
return (
<div className="root">
<Select
styles={styles}
isSearchable
isMulti
getOptionValue={(option) => option["value"]}
options={options}
value={values}
onChange={(options) => {
setValues(() => options);
}}
components={{
MultiValue: CustomMultiValue
}}
/>
</div>
);
}
自定义 selected 值
function CustomMultiValue(props) {
const { getValue, data } = props;
const selectedOptions = getValue();
const currentOptionIdx = selectedOptions.findIndex(
(option) => option.value === data.value
);
return (
<span>
{data.label}
{currentOptionIdx === selectedOptions.length - 1 ? "" : ", "}
</span>
);
}
沙盒项目https://codesandbox.io/s/boring-knuth-kfo1e?file=/src/CustomMultiValue.js
我认为您的代码没有任何问题。也许你应该尝试增加 Select
的宽度,这样你就可以看到所有其他 multi-values 被剪裁在你的 codesandbox 中。
const width = "500px";
const styles = {
control: (provided) => ({
...provided,
width
}),
menu: (provided) => ({
...provided,
width
}),
...
};
我找到了解决办法。 要实现它需要做 2 个操作:
- 在 select 打开时更改 ValueContainer 的溢出样式
- 菜单关闭时向左滚动
当菜单打开时使用 overflow:unset
- 因此输入将在 selected 值的末尾正确显示
当菜单关闭时,使用 overflow:ellipsis
显示第一个 selected 值并需要对它们进行切片
valueContainer: (provided, state) => {
const disableOverflow =
state.selectProps.isSearchable && state.selectProps.menuIsOpen;
return {
whiteSpace: "nowrap",
textOverflow: disableOverflow ? "unset" : "ellipsis",
overflow: "hidden",
flex: "1 1 0%",
position: "relative"
};
},
要向左滚动需要使用自定义 ValueContainer
并将 ref
传递给该容器。检查 menuIsOpen
何时更改为 false
并在那一刻向左滚动。
function CustomMultiValueContainer(props) {
const {
selectProps: { menuIsOpen }
} = props;
const containerRef = useRef(null);
const styles = props.getStyles("valueContainer", props);
useEffect(() => {
if (!menuIsOpen) {
if (containerRef && containerRef.current) {
containerRef.current.scrollLeft = 0;
}
}
}, [menuIsOpen]);
return (
<div ref={containerRef} style={styles}>
{props.children}
</div>
);
}