feat(upload): support itemRender (#26333)

This commit is contained in:
Kermit Xuan 2020-09-17 16:14:42 +08:00 committed by GitHub
parent 4a86b75c74
commit 7f7fe176e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 709 additions and 9 deletions

View File

@ -43,6 +43,7 @@ const InternalUpload: React.ForwardRefRenderFunction<unknown, UploadProps> = (pr
type,
children,
style,
itemRender,
} = props;
const [dragState, setDragState] = React.useState<string>('drop');
@ -261,6 +262,7 @@ const InternalUpload: React.ForwardRefRenderFunction<unknown, UploadProps> = (pr
isImageUrl={isImageUrl}
progress={progress}
appendAction={button}
itemRender={itemRender}
/>
);
}}

View File

@ -37,6 +37,7 @@ const InternalUploadList: React.ForwardRefRenderFunction<unknown, UploadListProp
downloadIcon: customDownloadIcon,
progress: progressProps,
appendAction,
itemRender,
},
ref,
) => {
@ -210,7 +211,9 @@ const InternalUploadList: React.ForwardRefRenderFunction<unknown, UploadListProp
const removeIcon = showRemoveIcon
? handleActionIconRender(
(typeof customRemoveIcon === 'function' ? customRemoveIcon(file) : customRemoveIcon) || <DeleteOutlined />,
(typeof customRemoveIcon === 'function' ? customRemoveIcon(file) : customRemoveIcon) || (
<DeleteOutlined />
),
() => handleClose(file),
prefixCls,
locale.removeFile,
@ -220,7 +223,9 @@ const InternalUploadList: React.ForwardRefRenderFunction<unknown, UploadListProp
const downloadIcon =
showDownloadIcon && file.status === 'done'
? handleActionIconRender(
(typeof customDownloadIcon=== 'function' ? customDownloadIcon(file) : customDownloadIcon) || <DownloadOutlined />,
(typeof customDownloadIcon === 'function'
? customDownloadIcon(file)
: customDownloadIcon) || <DownloadOutlined />,
() => handleDownload(file),
prefixCls,
locale.downloadFile,
@ -317,15 +322,17 @@ const InternalUploadList: React.ForwardRefRenderFunction<unknown, UploadListProp
const listContainerNameClass = classNames({
[`${prefixCls}-list-picture-card-container`]: listType === 'picture-card',
});
const item =
file.status === 'error' ? (
<Tooltip title={message} getPopupContainer={node => node.parentNode as HTMLElement}>
{dom}
</Tooltip>
) : (
<span>{dom}</span>
);
return (
<div key={file.uid} className={listContainerNameClass}>
{file.status === 'error' ? (
<Tooltip title={message} getPopupContainer={node => node.parentNode as HTMLElement}>
{dom}
</Tooltip>
) : (
<span>{dom}</span>
)}
{itemRender ? itemRender(item, file, items) : item}
</div>
);
});

View File

@ -690,6 +690,480 @@ exports[`renders ./components/upload/demo/drag.md correctly 1`] = `
</span>
`;
exports[`renders ./components/upload/demo/drag-sorting.md correctly 1`] = `
<span
class=""
>
<div
class="ant-upload ant-upload-select ant-upload-select-text"
>
<span
class="ant-upload"
role="button"
tabindex="0"
>
<input
accept=""
style="display:none"
type="file"
/>
<button
class="ant-btn"
type="button"
>
<span
aria-label="upload"
class="anticon anticon-upload"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="upload"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"
/>
</svg>
</span>
<span>
Click to Upload
</span>
</button>
</span>
</div>
<div
class="ant-upload-list ant-upload-list-text"
>
<div
class=""
>
<div
class="ant-upload-draggable-list-item "
style="cursor:move"
>
<span>
<div
class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-text"
>
<div
class="ant-upload-list-item-info"
>
<span>
<div
class="ant-upload-text-icon"
>
<span
aria-label="paper-clip"
class="anticon anticon-paper-clip"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="paper-clip"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z"
/>
</svg>
</span>
</div>
<a
class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1"
href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
rel="noopener noreferrer"
target="_blank"
title="image1.png"
>
image1.png
</a>
<span
class="ant-upload-list-item-card-actions "
>
<button
class="ant-btn ant-btn-text ant-btn-sm ant-btn-icon-only ant-upload-list-item-card-actions-btn"
title="Remove file"
type="button"
>
<span
aria-label="delete"
class="anticon anticon-delete"
role="img"
tabindex="-1"
>
<svg
aria-hidden="true"
class=""
data-icon="delete"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"
/>
</svg>
</span>
</button>
</span>
</span>
</div>
</div>
</span>
</div>
</div>
<div
class=""
>
<div
class="ant-upload-draggable-list-item "
style="cursor:move"
>
<span>
<div
class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-text"
>
<div
class="ant-upload-list-item-info"
>
<span>
<div
class="ant-upload-text-icon"
>
<span
aria-label="paper-clip"
class="anticon anticon-paper-clip"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="paper-clip"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z"
/>
</svg>
</span>
</div>
<a
class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1"
href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
rel="noopener noreferrer"
target="_blank"
title="image2.png"
>
image2.png
</a>
<span
class="ant-upload-list-item-card-actions "
>
<button
class="ant-btn ant-btn-text ant-btn-sm ant-btn-icon-only ant-upload-list-item-card-actions-btn"
title="Remove file"
type="button"
>
<span
aria-label="delete"
class="anticon anticon-delete"
role="img"
tabindex="-1"
>
<svg
aria-hidden="true"
class=""
data-icon="delete"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"
/>
</svg>
</span>
</button>
</span>
</span>
</div>
</div>
</span>
</div>
</div>
<div
class=""
>
<div
class="ant-upload-draggable-list-item "
style="cursor:move"
>
<span>
<div
class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-text"
>
<div
class="ant-upload-list-item-info"
>
<span>
<div
class="ant-upload-text-icon"
>
<span
aria-label="paper-clip"
class="anticon anticon-paper-clip"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="paper-clip"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z"
/>
</svg>
</span>
</div>
<a
class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1"
href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
rel="noopener noreferrer"
target="_blank"
title="image3.png"
>
image3.png
</a>
<span
class="ant-upload-list-item-card-actions "
>
<button
class="ant-btn ant-btn-text ant-btn-sm ant-btn-icon-only ant-upload-list-item-card-actions-btn"
title="Remove file"
type="button"
>
<span
aria-label="delete"
class="anticon anticon-delete"
role="img"
tabindex="-1"
>
<svg
aria-hidden="true"
class=""
data-icon="delete"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"
/>
</svg>
</span>
</button>
</span>
</span>
</div>
</div>
</span>
</div>
</div>
<div
class=""
>
<div
class="ant-upload-draggable-list-item "
style="cursor:move"
>
<span>
<div
class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-text"
>
<div
class="ant-upload-list-item-info"
>
<span>
<div
class="ant-upload-text-icon"
>
<span
aria-label="paper-clip"
class="anticon anticon-paper-clip"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="paper-clip"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z"
/>
</svg>
</span>
</div>
<a
class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1"
href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
rel="noopener noreferrer"
target="_blank"
title="image4.png"
>
image4.png
</a>
<span
class="ant-upload-list-item-card-actions "
>
<button
class="ant-btn ant-btn-text ant-btn-sm ant-btn-icon-only ant-upload-list-item-card-actions-btn"
title="Remove file"
type="button"
>
<span
aria-label="delete"
class="anticon anticon-delete"
role="img"
tabindex="-1"
>
<svg
aria-hidden="true"
class=""
data-icon="delete"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"
/>
</svg>
</span>
</button>
</span>
</span>
</div>
</div>
</span>
</div>
</div>
<div
class=""
>
<div
class="ant-upload-draggable-list-item "
style="cursor:move"
>
<div
class="ant-upload-list-item ant-upload-list-item-error ant-upload-list-item-list-type-text"
>
<div
class="ant-upload-list-item-info"
>
<span>
<div
class="ant-upload-text-icon"
>
<span
aria-label="paper-clip"
class="anticon anticon-paper-clip"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="paper-clip"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z"
/>
</svg>
</span>
</div>
<span
class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1"
title="image.png"
>
image.png
</span>
<span
class="ant-upload-list-item-card-actions "
>
<button
class="ant-btn ant-btn-text ant-btn-sm ant-btn-icon-only ant-upload-list-item-card-actions-btn"
title="Remove file"
type="button"
>
<span
aria-label="delete"
class="anticon anticon-delete"
role="img"
tabindex="-1"
>
<svg
aria-hidden="true"
class=""
data-icon="delete"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"
/>
</svg>
</span>
</button>
</span>
</span>
</div>
</div>
</div>
</div>
</div>
</span>
`;
exports[`renders ./components/upload/demo/file-type.md correctly 1`] = `
<span
class="ant-upload-picture-card-wrapper"

View File

@ -106,6 +106,31 @@ exports[`Upload List handle error 1`] = `
</span>
`;
exports[`Upload List itemRender 1`] = `
<div
class="ant-upload-list ant-upload-list-text"
>
<div
class=""
>
<span
class="custom-item-render"
>
uid:-1 name: xxx.png status: removed url: https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png 1/2
</span>
</div>
<div
class=""
>
<span
class="custom-item-render"
>
uid:-2 name: yyy.png status: removed url: https://zos.alipayobjects.com/rmsportal/IQKRngzUuFzJzGzRJXUs.png 2/2
</span>
</div>
</div>
`;
exports[`Upload List should be uploading when upload a file 1`] = `
<span
class=""

View File

@ -993,4 +993,20 @@ describe('Upload List', () => {
jest.useRealTimers();
});
it('itemRender', () => {
const itemRender = (originNode, file, currFileList) => {
const { name, status, uid, url } = file;
const index = currFileList.indexOf(file);
return (
<span className="custom-item-render">
{`uid:${uid} name: ${name} status: ${status} url: ${url} ${index + 1}/${
currFileList.length
}`}
</span>
);
};
const wrapper = mount(<UploadList locale={{}} items={fileList} itemRender={itemRender} />);
expect(wrapper.render()).toMatchSnapshot();
});
});

View File

@ -0,0 +1,164 @@
---
order: 13
title:
zh-CN: 上传列表拖拽排序
en-US: Drag sorting of uploadList
---
## zh-CN
使用 `itemRender` ,我们可以集成 react-dnd 来实现对上传列表拖拽排序。
## en-US
By using `itemRender`, we can integrate upload with react-dnd to implement drag sorting of uploadList.
```jsx
import React, { useState, useCallback, useRef } from 'react';
import { Upload, Button, Tooltip } from 'antd';
import { DndProvider, useDrag, useDrop, createDndContext } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import update from 'immutability-helper';
import { UploadOutlined } from '@ant-design/icons';
const RNDContext = createDndContext(HTML5Backend);
const type = 'DragableUploadList';
const DragableUploadListItem = ({ originNode, moveRow, file, fileList }) => {
const ref = React.useRef();
const index = fileList.indexOf(file);
const [{ isOver, dropClassName }, drop] = useDrop({
accept: type,
collect: monitor => {
const { index: dragIndex } = monitor.getItem() || {};
if (dragIndex === index) {
return {};
}
return {
isOver: monitor.isOver(),
dropClassName: dragIndex < index ? ' drop-over-downward' : ' drop-over-upward',
};
},
drop: item => {
moveRow(item.index, index);
},
});
const [, drag] = useDrag({
item: { type, index },
collect: monitor => ({
isDragging: monitor.isDragging(),
}),
});
drop(drag(ref));
const errorNode = (
<Tooltip title="Upload Error" getPopupContainer={() => document.body}>
{originNode.props.children}
</Tooltip>
);
return (
<div
ref={ref}
className={`ant-upload-draggable-list-item ${isOver ? dropClassName : ''}`}
style={{ cursor: 'move' }}
>
{file.status === 'error' ? errorNode : originNode}
</div>
);
};
const DragSortingUpload: React.FC = () => {
const [fileList, setFileList] = useState([
{
uid: '-1',
name: 'image1.png',
status: 'done',
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
},
{
uid: '-2',
name: 'image2.png',
status: 'done',
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
},
{
uid: '-3',
name: 'image3.png',
status: 'done',
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
},
{
uid: '-4',
name: 'image4.png',
status: 'done',
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
},
{
uid: '-5',
name: 'image.png',
status: 'error',
},
]);
const moveRow = useCallback(
(dragIndex, hoverIndex) => {
const dragRow = fileList[dragIndex];
setFileList(
update(fileList, {
$splice: [
[dragIndex, 1],
[hoverIndex, 0, dragRow],
],
}),
);
},
[fileList],
);
const manager = useRef(RNDContext);
const onChange = ({ fileList: newFileList }) => {
setFileList(newFileList);
};
return (
<DndProvider manager={manager.current.dragDropManager}>
<Upload
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
fileList={fileList}
onChange={onChange}
itemRender={(originNode, file, currFileList) => {
return (
<DragableUploadListItem
originNode={originNode}
file={file}
fileList={currFileList}
moveRow={moveRow}
/>
);
}}
>
<Button>
<UploadOutlined /> Click to Upload
</Button>
</Upload>
</DndProvider>
);
};
ReactDOM.render(<DragSortingUpload />, mountNode);
```
```css
#components-upload-demo-drag-sorting .ant-upload-draggable-list-item {
border-top: 2px dashed rgba(0, 0, 0, 0);
border-bottom: 2px dashed rgba(0, 0, 0, 0);
}
#components-upload-demo-drag-sorting .ant-upload-draggable-list-item.drop-over-downward {
border-bottom-color: #1890ff;
}
#components-upload-demo-drag-sorting .ant-upload-draggable-list-item.drop-over-upward {
border-top-color: #1890ff;
}
```

View File

@ -45,6 +45,7 @@ Uploading is the process of publishing information (web pages, text, pictures, v
| transformFile   | Customize transform file before request | Function(file): string \| Blob \| File \| Promise&lt;string \| Blob \| File> | - | |
| iconRender | Custom show icon | (file: UploadFile, listType?: UploadListType) => ReactNode | - | |
| progress | Custom progress bar | [ProgressProps](/components/progress/#API) (support `type="line"` only) | { strokeWidth: 2, showInfo: false } | 4.3.0 |
| itemRender | Custom item of uploadList | (originNode: ReactElement, file: UploadFile, fileList?: object\[]) => React.ReactNode | - | 4.7.0 |
### onChange

View File

@ -46,6 +46,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/QaeBt_ZMg/Upload.svg
| transformFile   | 在上传之前转换文件。支持返回一个 Promise 对象   | function(file): string \| Blob \| File \| Promise&lt;string \| Blob \| File> | -   | |
| iconRender | 自定义显示 icon | (file: UploadFile, listType?: UploadListType) => ReactNode | - | |
| progress | 自定义进度条样式 | [ProgressProps](/components/progress/#API)(仅支持 `type="line"` | { strokeWidth: 2, showInfo: false } | 4.3.0 |
| itemRender | 自定义上传列表项 | (originNode: ReactElement, file: UploadFile, fileList?: object\[]) => React.ReactNode | - | 4.7.0 |
### onChange

View File

@ -111,6 +111,11 @@ export interface UploadProps<T = any> {
iconRender?: (file: UploadFile<T>, listType?: UploadListType) => React.ReactNode;
isImageUrl?: (file: UploadFile) => boolean;
progress?: UploadListProgressProps;
itemRender?: (
originNode: React.ReactElement,
file: UploadFile,
fileList?: Array<UploadFile<T>>,
) => React.ReactNode;
}
export interface UploadState<T = any> {
@ -136,4 +141,9 @@ export interface UploadListProps<T = any> {
iconRender?: (file: UploadFile<T>, listType?: UploadListType) => React.ReactNode;
isImageUrl?: (file: UploadFile) => boolean;
appendAction?: React.ReactNode;
itemRender?: (
originNode: React.ReactElement,
file: UploadFile,
fileList?: Array<UploadFile<T>>,
) => React.ReactNode;
}