diff --git a/CHANGELOG.en-US.md b/CHANGELOG.en-US.md index 8a275f32926..c238837b3fc 100644 --- a/CHANGELOG.en-US.md +++ b/CHANGELOG.en-US.md @@ -11,6 +11,7 @@ - Add `n-carousel` component. - Add `useThemeVars` composable to provide theme variables. +- `n-upload` add `on-update:file-list` prop, closes [#135](https://github.com/TuSimple/naive-ui/issues/135). - `n-date-picker` add `update-value-on-close` prop. ### Fixes diff --git a/CHANGELOG.zh-CN.md b/CHANGELOG.zh-CN.md index 2c75f799157..44cbf8ccc00 100644 --- a/CHANGELOG.zh-CN.md +++ b/CHANGELOG.zh-CN.md @@ -11,6 +11,7 @@ - 新增 `n-carousel` 组件 - 新增 `useThemeVars` 函数提供主题变量 +- `n-upload` 新增 `on-update:file-list` 属性,关闭 [#135](https://github.com/TuSimple/naive-ui/issues/135) - `n-date-picker` 新增 `update-value-on-close` 属性 ### Fixes diff --git a/src/upload/demos/enUS/controlled.demo.md b/src/upload/demos/enUS/controlled.demo.md index 6d62e5c8051..f202ee22c44 100644 --- a/src/upload/demos/enUS/controlled.demo.md +++ b/src/upload/demos/enUS/controlled.demo.md @@ -5,7 +5,8 @@ Example is only a joke. ```html @@ -68,6 +69,9 @@ export default defineComponent({ }, 4000) }) } + }, + handleFileListChange (value) { + message.info("Yes, file-list changed.") } } } diff --git a/src/upload/demos/enUS/index.demo-entry.md b/src/upload/demos/enUS/index.demo-entry.md index 134e5fbb76c..e0384b5a7e2 100644 --- a/src/upload/demos/enUS/index.demo-entry.md +++ b/src/upload/demos/enUS/index.demo-entry.md @@ -36,6 +36,7 @@ default-files | show-retry-button | `boolean` | `true` | Whether to show retry button (at file error status). | | with-credentials | `boolean` | `false` | If cookie attached. | | on-change | `(options: { file: UploadFile, fileList: Array, event?: Event }) => void` | `() => {}` | The callback of status change of the component. Any file status change would fire the callback. | +| on-update:file-list | `(fileList: UploadFile[]) => void` | `undefined` | Callback function triggered on fileList changes. | | on-finish | `(options: { file: UploadFile }) => UploadFile \| void` | `({ file }) => file` | The callback of file upload finish. You can modify the UploadFile or retun a new UploadFile. | | on-remove | `(options: { file: UploadFile, fileList: Array }) => boolean \| Promise \| any` | `() => true` | The callback of file removal. Return false, promise resolve false or promise reject will cancel this removal. | @@ -49,14 +50,6 @@ default-files | percentage | `number` | The progress percentage of file upload. It works when file is uploading. Not required in controlled manner. | | file | `File` | The File object of the file in brower. Not required in controlled manner. | -## Events - -### Upload Events - -| Name | Parameters | Description | -| ------ | ------------------------------------------------- | ----------- | -| change | `(file: UploadFile, fileList: Array)` | | - ## Methods ### Upload Methods diff --git a/src/upload/demos/zhCN/controlled.demo.md b/src/upload/demos/zhCN/controlled.demo.md index dadfe122365..a207723216c 100644 --- a/src/upload/demos/zhCN/controlled.demo.md +++ b/src/upload/demos/zhCN/controlled.demo.md @@ -5,9 +5,10 @@ ```html 上传文件 @@ -65,6 +66,9 @@ export default defineComponent({ }, 4000) }) } + }, + handleFileListChange (value) { + message.info("是的,file-list 的值变了") } } } diff --git a/src/upload/demos/zhCN/index.demo-entry.md b/src/upload/demos/zhCN/index.demo-entry.md index e98c9d7a0e6..e236ee0c23a 100644 --- a/src/upload/demos/zhCN/index.demo-entry.md +++ b/src/upload/demos/zhCN/index.demo-entry.md @@ -37,6 +37,7 @@ default-files | with-credentials | `boolean` | `false` | 是否携带 Cookie | | on-change | `(options: { file: UploadFile, fileList: Array, event?: Event }) => void` | `() => {}` | 组件状态变化的回调,组件的任何文件状态变化都会触发回调 | | on-finish | `(options: { file: UploadFile }) => UploadFile \| void` | `({ file }) => file` | 文件上传结束的回调,可以修改传入的 UploadFile 或者返回一个新的 UploadFile | +| on-update:file-list | `(fileList: UploadFile[]) => void` | `undefined` | 当 file-list 改变时触发的回调函数 | | on-remove | `(options: { file: UploadFile, fileList: Array }) => boolean \| Promise \| any` | `() => true` | 文件移除的回调,返回 false 或者 promise resolve false 或者 promise reject 会不执行这次删除 | ### UploadFile Type diff --git a/src/upload/src/Upload.tsx b/src/upload/src/Upload.tsx index a211991a4ce..c85cec12cf8 100644 --- a/src/upload/src/Upload.tsx +++ b/src/upload/src/Upload.tsx @@ -11,7 +11,7 @@ import { import { createId } from 'seemly' import { useConfig, useTheme } from '../../_mixins' import type { ThemeProps } from '../../_mixins' -import { ExtractPublicPropTypes, getFirstSlotVNode, warn } from '../../_utils' +import { ExtractPublicPropTypes, getFirstSlotVNode, warn, MaybeArray, call } from '../../_utils' import { NFadeInExpandTransition } from '../../_internal' import { uploadLight, UploadTheme } from '../styles' import NUploadFile from './UploadFile' @@ -26,7 +26,8 @@ import { OnRemove, OnDownload, OnChange, - uploadInjectionKey + uploadInjectionKey, + OnUpdateFileList } from './interface' import { useMergedState } from 'vooks' import { uploadDraggerKey } from './UploadDragger' @@ -209,6 +210,12 @@ const uploadProps = { default: true }, fileList: Array as PropType, + 'onUpdate:fileList': [Function, Array] as PropType< + MaybeArray + >, + onUpdateFileList: [Function, Array] as PropType< + MaybeArray + >, fileListStyle: [String, Object] as PropType, defaultFileList: { type: Array as PropType, @@ -248,6 +255,7 @@ export default defineComponent({ mergedClsPrefixRef ) const uncontrolledFileListRef = ref(props.defaultFileList) + const controlledFileListRef = toRef(props, 'fileList') const inputElRef = ref(null) const draggerInsideRef = { value: false @@ -255,7 +263,7 @@ export default defineComponent({ const dragOverRef = ref(false) const XhrMap = new Map() const mergedFileListRef = useMergedState( - toRef(props, 'fileList'), + controlledFileListRef, uncontrolledFileListRef ) function openFileDialog (): void { @@ -293,6 +301,15 @@ export default defineComponent({ // May have bug! set to null? target.value = '' } + function doUpdateFileList (files: FileInfo[]): void { + const { + 'onUpdate:fileList': _onUpdateFileList, + onUpdateFileList, + } = props + if (_onUpdateFileList) call(_onUpdateFileList, files) + if (onUpdateFileList) call(onUpdateFileList, files) + uncontrolledFileListRef.value = files + } function handleFileAddition (files: FileList | null, e?: Event): void { if (!files) return Array.from(files).forEach((file) => { @@ -378,7 +395,7 @@ export default defineComponent({ event }) } - uncontrolledFileListRef.value = fileListAfterChange + doUpdateFileList(fileListAfterChange) } else if (__DEV__) { warn('upload', 'File has no corresponding id in current file list.') } diff --git a/src/upload/src/interface.ts b/src/upload/src/interface.ts index cce2bd3d3dc..073655236f0 100644 --- a/src/upload/src/interface.ts +++ b/src/upload/src/interface.ts @@ -43,6 +43,8 @@ export type DoChange = ( } ) => void +export type OnUpdateFileList = (fileList: FileInfo[]) => void + export interface UploadInjection { mergedClsPrefixRef: Ref mergedThemeRef: Ref>