React + Antd + Ts Customize the Select selection box to select all functions (two different styles)
- The first default style
import React from 'react';
import {
Select, Checkbox } from 'antd';
const {
Option } = Select;
interface Option {
label: string;
value: string;
}
interface SelectProps {
options: Option[];
}
const SelectWithCheckbox: React.FC<SelectProps> = ({
options }) => {
const [selectedValues, setSelectedValues] = React.useState<string[]>([]);
const handleSelectChange = (values: string[]) => {
setSelectedValues(values);
};
return (
<Select
style={
{
width: 400 }}
mode="multiple"
onChange={
handleSelectChange}
maxTagCount={
3}
value={
selectedValues}
dropdownRender={
(menu) => (
<div>
<div onClick={
(e) => e.stopPropagation()}>
// 因为option.value可能为undefined,但是这里不允许undefined,所以加!
<a
onClick={
() =>
handleSelectChange(options.map((option) => option.value!))
}
style={
{
display: 'block', margin: '10px 10px' }}
>
选择所有
</a>
</div>
{
menu}
</div>
)}
>
{
options.map((option) => (
<Option key={
option.value} value={
option.value}>
{
option.label}
</Option>
))}
</Select>
);
};
export default SelectWithCheckbox;
-
The second type of selection box with checkbox (with search)
import React , { useState} from 'react'; import { Select, Checkbox,Empty } from 'antd'; import './index.less'; const { Option } = Select; interface Option { label: string; value: string; } interface SelectProps { options: Option[]; style?: React.CSSProperties; placeholder?: string; onChange?: (values: string[]) => void; } const SelectWithCheckbox: React.FC<SelectProps> = ({ options, style, placeholder, onChange, }) => { const [selectedValues, setSelectedValues] = useState<string[]>([]); const [searchKeyword, setSearchKeyword] = useState(''); const [isSearchEmpty, setIsSearchEmpty] = useState(false); const handleSelectChange = (values: string[]) => { setSelectedValues(values); searchKeyword && setSearchKeyword(''); onChange && onChange(values); }; const handleSearch = (value: string) => { setSearchKeyword(value); setIsSearchEmpty( options.filter((option) => option.label.toLowerCase().includes(value.toLowerCase()), ).length === 0, ); }; const handleAllOptionSelect = ( event: React.ChangeEvent<HTMLInputElement>, ) => { if (event.target.checked) { handleSelectChange(options.map((option) => option.value!)); } else { handleSelectChange([]); } }; const isAllOptionSelected = () => { const selectedOptions = options .filter( (option) => option.value !== undefined && option.value !== null && option.value !== '', ) .map((option) => option.value!); return ( selectedOptions.length > 0 && selectedOptions.every((value) => selectedValues.indexOf(value) !== -1) ); }; return ( <Select style={ { width: '100%', ...style }} placeholder={ placeholder} className="select-with-checkbox" mode="multiple" onChange={ handleSelectChange} value={ selectedValues} onSearch={ (value) => handleSearch(value)} maxTagCount={ 3} getPopupContainer={ (triggerNode) => triggerNode.parentNode} maxTagPlaceholder={ (omittedValues) => `+ ${ omittedValues.length} 项`} dropdownRender={ (menu) => ( <div className="my-select-wrapper"> { !searchKeyword && ( <div onClick={ (e) => e.stopPropagation()} className="my-menu-all"> <Checkbox checked={ isAllOptionSelected()} onChange={ handleAllOptionSelect as any} style={ { width: '100%', padding: '5px 20px' }} > 全部 </Checkbox> </div> )} { isSearchEmpty ? ( <div className="my-empty"> <Empty image={ Empty.PRESENTED_IMAGE_SIMPLE} /> </div> ) : ( options .filter((option) => option.label .toLowerCase() .includes(searchKeyword.toLowerCase()), ) .map((option) => ( <div key={ option.value} onClick={ (e) => e.stopPropagation()} className="my-menu-item" > <Checkbox checked={ selectedValues.indexOf(option.value) !== -1} onChange={ (e) => { const nextSelectedValues = e.target.checked ? [...selectedValues, option.value] : selectedValues.filter( (value) => value !== option.value, ); handleSelectChange(nextSelectedValues); }} style={ { width: '100%', padding: '5px 20px' }} > { option.label} </Checkbox> </div> )) )} </div> )} > { options.map((option) => ( <Option key={ option.value} value={ option.value}> { option.label} </Option> ))} </Select> ); }; export default SelectWithCheckbox;
index.less style file
.select-with-checkbox { .ant-select-selector { height: 36px; border: 1px solid #ebebeb !important; border-radius: 6px !important; .ant-select-selection-item { height: 25px; background: #f2f9ff; border-radius: 4px 4px 4px 4px; border: 1px solid #a0d1ff; .ant-select-selection-item-content { display: flex; align-items: center; color: #1f91fc; } .ant-select-selection-item-remove { font-size: 12px; &:hover { color: #1e91fe; } } } } } .my-select-wrapper { max-height: 320px; overflow-y: auto; } .my-menu-all { cursor: pointer; &:hover { font-weight: 600; background-color: #f5f5f5; } .ant-checkbox-wrapper-checked { font-weight: 600; background-color: #e6f7ff; } } .my-menu-item { cursor: pointer; &:hover { font-weight: 600; background-color: #f5f5f5; } .ant-checkbox-wrapper-checked { font-weight: 600; background-color: #e6f7ff; } }