Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

form Checkbox.Group 缺少全选API #28299

Closed
1 task done
aLIEzsss4 opened this issue Dec 10, 2020 · 6 comments
Closed
1 task done

form Checkbox.Group 缺少全选API #28299

aLIEzsss4 opened this issue Dec 10, 2020 · 6 comments
Labels
help wanted The suggestion or request has been accepted, we need you to help us by sending a pull request. Inactive

Comments

@aLIEzsss4
Copy link
Contributor

aLIEzsss4 commented Dec 10, 2020

  • I have searched the issues of this repository and believe that this is not a duplicate.

Reproduction link

Edit on CodeSandbox

What problem does this feature solve?

在form 表单里的 Checkbox.Group 只能通过受控属性去全选/全不选,需要增加一个API减少代码量

What does the proposed API look like?

const options=[
  { label: 'Apple', value: 'Apple' },
  { label: 'Pear', value: 'Pear' },
  { label: 'Orange', value: 'Orange' },
]
const checkAllLabel='check all'

<Form.Item>
  <Checkbox.Group options={options} checkAllLabel={checkAllLabel}  />
</Form.Item>


添加checkAllOption会默认加在options数组第0项进行渲染,并且具有全选/全不选的功能
@afc163 afc163 added the help wanted The suggestion or request has been accepted, we need you to help us by sending a pull request. label Dec 12, 2020
@ant-design-bot
Copy link
Contributor

Hello @aLIEzsss4. We totally like your proposal/feedback, welcome to send us a Pull Request for it. Please send your Pull Request to proper branch (feature branch for the new feature, master for bugfix and other changes), fill the Pull Request Template here, provide changelog/TypeScript/documentation/test cases if needed and make sure CI passed, we will review it soon. We appreciate your effort in advance and looking forward to your contribution!

你好 @aLIEzsss4, 我们完全同意你的提议/反馈,欢迎直接在此仓库 创建一个 Pull Request 来解决这个问题。请将 Pull Request 发到正确的分支(新特性发到 feature 分支,其他发到 master 分支),务必填写 Pull Request 内的预设模板,提供改动所需相应的 changelog、TypeScript 定义、测试用例、文档等,并确保 CI 通过,我们会尽快进行 Review,提前感谢和期待您的贡献!

giphy

@AnathanPham
Copy link

AnathanPham commented Dec 22, 2020

目前的Checkbox.Group完全满足需求。
我认为不需要为Checkbox.Group添加这样的字段

全选

<Checkbox.Group options={options} value={options}  />

全不选

<Checkbox.Group options={options} value={[]}  />

为何需要额外添加一个字段来表示全选和全不选呢?“需要增加一个API减少代码量”,你想减少什么代码?

@kerm1it
Copy link
Member

kerm1it commented Dec 22, 2020

他需要单独加一个 option 来支持全选或全不选。

@aLIEzsss4
Copy link
Contributor Author

https://codesandbox.io/s/eu3zs?file=/index.tsx
先上链接,为了在Form.Item里使用,不得不编写很多受控组件的逻辑。

import { Form, Button, Checkbox } from "antd";
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import "antd/dist/antd.css";

interface Props {
  disabled?: boolean;
}

export const CheckboxTimeGroup = (props: any) => {
  const { disabled, onChange, value, checkAllLabel, options } = props;
  const [checkAll, setCheckAll] = useState(false);
  const [indeterminate, setIndeterminate] = React.useState(false);
  const timeMapList1Val = options?.map((v: { value: any }) => v.value);

  useEffect(() => {
    const mapVal = options?.map((v: { value: any }) => v.value);
    const defaultFlag = () => {
      if (!value || !mapVal) {
        return { checkAll: false, indeterminate: false };
      }
      let num = 0;
      value?.forEach((v: any) => {
        if (mapVal.indexOf(v) > -1) {
          num += 1;
        }
      });
      return {
        checkAll: (num && num === mapVal.length) || false,
        indeterminate: (num && num < mapVal.length) || false
      };
    };
    const defaultFlagVal = defaultFlag();
    setIndeterminate(defaultFlagVal.indeterminate);
    setCheckAll(defaultFlagVal.checkAll);
    return () => {};
  }, [value, options]);

  // 选择所有
  const onCheckAllChange = (e: {
    target: { checked: React.SetStateAction<boolean> };
  }) => {
    // 如果不全选就是空
    const list = e.target.checked ? timeMapList1Val : [];
    onChange(list);
    setCheckAll(e.target.checked);
    setIndeterminate(false);
  };

  // 单个项选择
  const onChangeGroup = (list: any[]) => {
    onChange(list);
    setIndeterminate(!!list.length && list.length < timeMapList1Val.length);
    setCheckAll(list.length === timeMapList1Val.length);
  };

  return (
    <div>
      <Checkbox
        indeterminate={indeterminate}
        onChange={onCheckAllChange}
        checked={checkAll}
        disabled={disabled}
      >
        {checkAllLabel}
      </Checkbox>
      <Checkbox.Group
        value={props.value}
        onChange={onChangeGroup}
        options={options}
        disabled={disabled}
      />
    </div>
  );
};

export const TimePick: React.FC<Props> = ({ disabled }) => {
  const onFinish = (values: any) => {
    console.log(values);
  };

  const timeMapList1 = ["一", "二", "三", "四", "五"].map((j, i) => ({
    label: `周${j}`,
    value: i + 1
  }));

  const checkAllLabel1 = "工作日";
  return (
    <Form onFinish={onFinish}>
      <Form.Item name="timeMap" key="timeMap">
        <CheckboxTimeGroup
          disabled={disabled}
          options={timeMapList1}
          checkAllLabel={checkAllLabel1}
        />
      </Form.Item>
      <Button type="primary" htmlType="submit">
        提交
      </Button>
    </Form>
  );
};

ReactDOM.render(<TimePick />, document.getElementById("container"));

我这么写对吗

@AnathanPham
Copy link

  const [checkAll, setCheckAll] = useState(false);
  const [indeterminate, setIndeterminate] = React.useState(false);

我认为这两个state应该作为依赖value和options的计算属性,而不是state。
因为checkAll、indeterminate的值本身应该是value和options计算得到的,用计算属性表示它们可以确保数据是正确的。

@aLIEzsss4
Copy link
Contributor Author

感谢,改了下

import { Form, Button, Checkbox } from "antd";
import React, { useMemo } from "react";
import ReactDOM from "react-dom";
import "antd/dist/antd.css";

interface Props {
  disabled?: boolean;
}

export const CheckboxTimeGroup = (props: any) => {
  const { onChange, value, checkAllLabel, options } = props;
  const { checkAll, indeterminate } = useMemo(() => {
    if (!value || !options) {
      return {
        checkAll: false,
        indeterminate: false
      };
    }
    return {
      checkAll: value.length === options.length,
      indeterminate: !!value.length && value.length < options.length
    };
  }, [value, options]);

  // 选择所有
  const onChangeCheckAll = (e: {
    target: { checked: React.SetStateAction<boolean> };
  }) => {
    // 如果不全选就是空
    const list = e.target.checked
      ? options?.map((v: { value: any }) => v.value)
      : [];
    onChange(list);
  };

  // 单个项选择
  const onChangeGroup = (list: any[]) => {
    onChange(list);
  };

  return (
    <div>
      <Checkbox
        {...props}
        indeterminate={indeterminate}
        onChange={onChangeCheckAll}
        checked={checkAll}
      >
        {checkAllLabel}
      </Checkbox>
      <Checkbox.Group {...props} onChange={onChangeGroup} />
    </div>
  );
};

export const TimePick: React.FC<Props> = ({ disabled }) => {
  const onFinish = (values: any) => {
    console.log(values);
  };

  const timeMapList1 = ["一", "二", "三", "四", "五"].map((j, i) => ({
    label: `周${j}`,
    value: i + 1
  }));

  const checkAllLabel1 = "工作日";
  return (
    <Form onFinish={onFinish}>
      <Form.Item name="timeMap" key="timeMap">
        <CheckboxTimeGroup
          disabled={disabled}
          options={timeMapList1}
          checkAllLabel={checkAllLabel1}
        />
      </Form.Item>
      <Button type="primary" htmlType="submit">
        提交
      </Button>
    </Form>
  );
};

ReactDOM.render(<TimePick />, document.getElementById("container"));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted The suggestion or request has been accepted, we need you to help us by sending a pull request. Inactive
Projects
None yet
Development

No branches or pull requests

6 participants