diff --git a/components/table/__tests__/Table.rowSelection.test.js b/components/table/__tests__/Table.rowSelection.test.js index 5e17b250f2..ca052cf037 100644 --- a/components/table/__tests__/Table.rowSelection.test.js +++ b/components/table/__tests__/Table.rowSelection.test.js @@ -865,6 +865,74 @@ describe('Table.rowSelection', () => { expect(wrapper.find('thead .ant-checkbox-input').props().checked).toBeFalsy(); }); + it('should make select all checked when each item is checked and disabled', () => { + const wrapper = mount( + createTable({ + rowSelection: { + selectedRowKeys: [0, 1, 2, 3], + getCheckboxProps: () => ({ + disabled: true, + }), + }, + }), + ); + + expect(wrapper.find('thead .ant-checkbox-input').props().disabled).toBeTruthy(); + expect(wrapper.find('thead .ant-checkbox-input').props().checked).toBeTruthy(); + }); + + it('should make select all indeterminated when each item is disabled and some item is checked', () => { + const wrapper = mount( + createTable({ + rowSelection: { + selectedRowKeys: [0], + getCheckboxProps: () => ({ + disabled: true, + }), + }, + }), + ); + + expect(wrapper.find('thead .ant-checkbox-input').props().disabled).toBeTruthy(); + expect(wrapper.find('thead .ant-checkbox-input').props().checked).toBeFalsy(); + expect( + wrapper.find('thead .ant-checkbox-indeterminate.ant-checkbox-disabled').exists(), + ).toBeTruthy(); + }); + + it('should make select all checked when each item is checked and some item is disabled', () => { + const wrapper = mount( + createTable({ + rowSelection: { + selectedRowKeys: [0, 1, 2, 3], + getCheckboxProps: record => ({ + disabled: record.key === 0, + }), + }, + }), + ); + + expect(wrapper.find('thead .ant-checkbox-input').props().disabled).toBeFalsy(); + expect(wrapper.find('thead .ant-checkbox-input').props().checked).toBeTruthy(); + }); + + it('should not make select all checked when some item is checked and disabled', () => { + const wrapper = mount( + createTable({ + rowSelection: { + selectedRowKeys: [1], + getCheckboxProps: record => ({ + disabled: record.key === 0, + }), + }, + }), + ); + + expect(wrapper.find('thead .ant-checkbox-input').props().disabled).toBeFalsy(); + expect(wrapper.find('thead .ant-checkbox-input').props().checked).toBeFalsy(); + expect(wrapper.find('thead .ant-checkbox-indeterminate').exists()).toBeTruthy(); + }); + it('should onRowClick not called when checkbox clicked', () => { const onRowClick = jest.fn(); diff --git a/components/table/hooks/useSelection.tsx b/components/table/hooks/useSelection.tsx index ec822f9897..b19b83302d 100644 --- a/components/table/hooks/useSelection.tsx +++ b/components/table/hooks/useSelection.tsx @@ -124,7 +124,7 @@ export default function useSelection( () => checkStrictly ? { keyEntities: null } - : convertDataToEntities((data as unknown) as DataNode[], { + : convertDataToEntities(data as unknown as DataNode[], { externalGetKey: getRowKey as any, childrenPropName: childrenColumnName, }), @@ -132,10 +132,10 @@ export default function useSelection( ); // Get flatten data - const flattedData = useMemo(() => flattenData(pageData, childrenColumnName), [ - pageData, - childrenColumnName, - ]); + const flattedData = useMemo( + () => flattenData(pageData, childrenColumnName), + [pageData, childrenColumnName], + ); // Get all checkbox props const checkboxPropsMap = useMemo(() => { @@ -395,17 +395,33 @@ export default function useSelection( ); } - const allDisabled = flattedData.every((record, index) => { - const key = getRowKey(record, index); - const checkboxProps = checkboxPropsMap.get(key) || {}; - return checkboxProps.disabled; - }); + const allDisabledData = flattedData + .map((record, index) => { + const key = getRowKey(record, index); + const checkboxProps = checkboxPropsMap.get(key) || {}; + return { checked: keySet.has(key), ...checkboxProps }; + }) + .filter(({ disabled }) => disabled); + + const allDisabled = + !!allDisabledData.length && allDisabledData.length === flattedData.length; + + const allDisabledAndChecked = + allDisabled && allDisabledData.every(({ checked }) => checked); + const allDisabledSomeChecked = + allDisabled && allDisabledData.some(({ checked }) => checked); title = !hideSelectAll && (