React + Antd + Ts 自定义Select选择框 全选功能(两种不同样式)

React + Antd + Ts 自定义Select选择框 全选功能(两种不同样式)

  • 第一种默认样式

在这里插入图片描述

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;

  • 第二种带复选框的选择框(带搜索)
    在这里插入图片描述

    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 样式文件

    .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;
      }
    }
    
    
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值