Skip to content

Commit 290add5

Browse files
zenggpzqbxafc163
andauthored
fix(Transfer): Prioritize using the disabled property of the Transfer component (ant-design#56093)
Co-authored-by: afc163 <afc163@gmail.com>
1 parent ab3569c commit 290add5

3 files changed

Lines changed: 87 additions & 6 deletions

File tree

components/transfer/ListBody.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ const TransferListBody: React.ForwardRefRenderFunction<
137137
onClick={onInternalClick}
138138
onRemove={onRemove}
139139
checked={selectedKeys.includes(item.key)}
140-
disabled={globalDisabled || item.disabled}
140+
disabled={globalDisabled}
141141
/>
142142
))}
143143
</ul>

components/transfer/ListItem.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ const ListItem = <RecordType extends KeyWiseTransferItem>(props: ListItemProps<R
3636
onRemove,
3737
showRemove,
3838
} = props;
39-
39+
const mergedDisabled = disabled || item?.disabled;
4040
const classes = clsx(`${prefixCls}-content-item`, classNames.item, {
41-
[`${prefixCls}-content-item-disabled`]: disabled || item.disabled,
41+
[`${prefixCls}-content-item-disabled`]: mergedDisabled,
4242
[`${prefixCls}-content-item-checked`]: checked && !item.disabled,
4343
});
4444

@@ -70,7 +70,7 @@ const ListItem = <RecordType extends KeyWiseTransferItem>(props: ListItemProps<R
7070
{labelNode}
7171
<button
7272
type="button"
73-
disabled={disabled || item.disabled}
73+
disabled={mergedDisabled}
7474
className={`${prefixCls}-content-item-remove`}
7575
aria-label={contextLocale?.remove}
7676
onClick={() => onRemove?.(item)}
@@ -82,15 +82,15 @@ const ListItem = <RecordType extends KeyWiseTransferItem>(props: ListItemProps<R
8282
}
8383

8484
// Default click to select
85-
liProps.onClick = disabled || item.disabled ? undefined : (event) => onClick(item, event);
85+
liProps.onClick = mergedDisabled ? undefined : (event) => onClick(item, event);
8686

8787
return (
8888
<li {...liProps}>
8989
<Checkbox
9090
className={clsx(`${prefixCls}-checkbox`, classNames.itemIcon)}
9191
style={styles.itemIcon}
9292
checked={checked}
93-
disabled={disabled || item.disabled}
93+
disabled={mergedDisabled}
9494
/>
9595
{labelNode}
9696
</li>

components/transfer/__tests__/index.test.tsx

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import mountTest from '../../../tests/shared/mountTest';
88
import rtlTest from '../../../tests/shared/rtlTest';
99
import { waitFakeTimer } from '../../../tests/utils';
1010
import Button from '../../button';
11+
import Checkbox from '../../checkbox';
1112
import ConfigProvider from '../../config-provider';
1213
import Form from '../../form';
1314

@@ -991,6 +992,86 @@ describe('Transfer', () => {
991992
expect(transfers[0]).not.toHaveClass('ant-transfer-disabled');
992993
expect(transfers[1]).toHaveClass('ant-transfer-disabled');
993994
});
995+
996+
it('prioritize using the disabled property of the Transfer component', () => {
997+
const App: React.FC = () => {
998+
const mockData = Array.from({ length: 20 }).map((_, i) => ({
999+
key: i.toString(),
1000+
title: `content${i + 1}`,
1001+
description: `description of content${i + 1}`,
1002+
disabled: i <= 5,
1003+
}));
1004+
const initialTargetKeys = mockData
1005+
.filter((item) => Number(item.key) > 10)
1006+
.map((item) => item.key);
1007+
const [componentDisabled, setComponentDisabled] = useState<boolean>(true);
1008+
const [transferDisabled, setTransferDisabled] = useState<boolean>(true);
1009+
const [targetKeys] = useState<TransferProps['targetKeys']>(initialTargetKeys);
1010+
const [selectedKeys] = useState<TransferProps['targetKeys']>([]);
1011+
return (
1012+
<>
1013+
<Checkbox
1014+
checked={componentDisabled}
1015+
onChange={(e) => setComponentDisabled(e.target.checked)}
1016+
>
1017+
Form disabled
1018+
</Checkbox>
1019+
<Checkbox
1020+
checked={transferDisabled}
1021+
onChange={(e) => setTransferDisabled(e.target.checked)}
1022+
>
1023+
Transfer disabled
1024+
</Checkbox>
1025+
<Form
1026+
labelCol={{ span: 4 }}
1027+
wrapperCol={{ span: 14 }}
1028+
layout="horizontal"
1029+
disabled={componentDisabled}
1030+
style={{ maxWidth: 600 }}
1031+
>
1032+
<Form.Item label="Transfer">
1033+
<Transfer
1034+
dataSource={mockData}
1035+
titles={['Source', 'Target']}
1036+
targetKeys={targetKeys}
1037+
selectedKeys={selectedKeys}
1038+
disabled={transferDisabled}
1039+
render={(item) => item.title}
1040+
/>
1041+
</Form.Item>
1042+
</Form>
1043+
</>
1044+
);
1045+
};
1046+
const { container } = render(<App />);
1047+
const transfer = container.querySelector('.ant-transfer');
1048+
const checkboxes = container.querySelectorAll('.ant-checkbox-input');
1049+
const formCheck: HTMLInputElement = checkboxes[0] as HTMLInputElement;
1050+
const transferCheck: HTMLInputElement = checkboxes[1] as HTMLInputElement;
1051+
1052+
expect(formCheck.checked).toBe(true);
1053+
expect(transferCheck.checked).toBe(true);
1054+
expect(transfer).toHaveClass('ant-transfer-disabled');
1055+
1056+
fireEvent.click(transferCheck);
1057+
expect(formCheck.checked).toBe(true);
1058+
expect(transferCheck.checked).toBe(false);
1059+
expect(container.querySelectorAll('.ant-transfer-list-content-item-disabled')).toHaveLength(
1060+
6,
1061+
);
1062+
1063+
fireEvent.click(formCheck);
1064+
expect(formCheck.checked).toBe(false);
1065+
expect(transferCheck.checked).toBe(false);
1066+
expect(container.querySelectorAll('.ant-transfer-list-content-item-disabled')).toHaveLength(
1067+
6,
1068+
);
1069+
1070+
fireEvent.click(transferCheck);
1071+
expect(formCheck.checked).toBe(false);
1072+
expect(transferCheck.checked).toBe(true);
1073+
expect(transfer).toHaveClass('ant-transfer-disabled');
1074+
});
9941075
});
9951076
});
9961077

0 commit comments

Comments
 (0)