diff --git a/CHANGELOG.md b/CHANGELOG.md index b21596165..6c0de2992 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # 更新日志 ## 3.5.0 +- 新增 `Form` SchemaForm 中 component 属性接受 ReactNode,SchemaForm 新增 updateSchema 更新函数 [#1612](https://github.com/XiaoMi/hiui/issues/1612) - 新增 `DatePicker` onSelect 选择日期的回调函数 [#1592](https://github.com/XiaoMi/hiui/issues/1592) - 新增 `Transfer` 组件 render 自定义菜单渲染函数 [#1575](https://github.com/XiaoMi/hiui/issues/1575) - 修复 `DatePicker` type 为 week 或者 weekrange 时 输入相应格式日期解析错误问题 [#1579](https://github.com/XiaoMi/hiui/issues/1579) diff --git a/components/date-picker/BasePicker.jsx b/components/date-picker/BasePicker.jsx index 369780753..55240fbd0 100644 --- a/components/date-picker/BasePicker.jsx +++ b/components/date-picker/BasePicker.jsx @@ -43,6 +43,8 @@ const BasePicker = ({ bordered = true, disabledDate, onSelect: propsOnSelect, + setOverlayContainer, + overlayClickOutSideEventName = 'click', ...otherPorps }) => { // 兼容2.x api -> max,min @@ -228,6 +230,8 @@ const BasePicker = ({ width={false} className={popperCls} placement={placement} + setOverlayContainer={setOverlayContainer} + overlayClickOutSideEventName={overlayClickOutSideEventName} onClickOutside={clickOutsideEvent} > {type.includes('range') || type === 'timeperiod' ? : } diff --git a/components/form/Form.js b/components/form/Form.js index ad107b4bf..6ca3be311 100644 --- a/components/form/Form.js +++ b/components/form/Form.js @@ -27,6 +27,7 @@ const InternalForm = (props) => { innerRef: formRef, initialValues, onValuesChange, + updateFormSchema, _type // SchemaForm 内部配置变量 } = props const _Immutable = useRef(new Immutable()) @@ -192,7 +193,8 @@ const InternalForm = (props) => { resetValidates, validateField, validate, - setFieldsValue + setFieldsValue, + updateFormSchema } }, [fields]) diff --git a/components/form/SchemaForm.js b/components/form/SchemaForm.js index 7ec77b2f5..eea5fac9c 100644 --- a/components/form/SchemaForm.js +++ b/components/form/SchemaForm.js @@ -18,6 +18,32 @@ const FormComponent = Provider(Form) const InternalSchemaForm = (props) => { const { schema: schemaProps, children: childrenProps, submit, reset, innerRef } = props const [schema, setSchema] = useState(schemaProps) + const updateSchema = useCallback( + (schemaItems = {}) => { + let _schema = _.cloneDeep(schema) + _schema = _schema.map((item) => { + const _item = _.cloneDeep(item) + const { field } = _item + const schemaItem = schemaItems[field] + if (field && schemaItem) { + const mergeSchema = _.mergeWith( + { [field]: { ..._item } }, + { [field]: { ...schemaItem } }, + (objValue, srcValue) => { + if (_.isArray(objValue)) { + return srcValue + } + } + ) + return mergeSchema[field] + } + return item + }) + setSchema(_schema) + }, + [schema] + ) + useEffect(() => { setSchema(schemaProps) }, [schemaProps]) @@ -31,7 +57,7 @@ const InternalSchemaForm = (props) => { const ChildComponent = HIUI[component] || Group[component] child = } else { - child =

{'not found ' + component}

+ child = component } return React.createElement(FormItem, { ..._.omit(schemaItem, 'component', 'componentProps'), @@ -43,7 +69,12 @@ const InternalSchemaForm = (props) => { }, [schema]) return (
- + {renderSchemaFormItem()} {childrenProps} {(submit || reset) && ( diff --git a/components/form/index.d.ts b/components/form/index.d.ts index 53f2264f8..d39e9971f 100644 --- a/components/form/index.d.ts +++ b/components/form/index.d.ts @@ -23,7 +23,7 @@ interface ItemProps { showColon?: boolean } interface SchemaItem extends ItemProps { - component?: string + component?: string | JSX.Element componentProps?: string } interface SchemaProps { diff --git a/components/popper/Overlay.js b/components/popper/Overlay.js index 7348ceedf..dd9905781 100644 --- a/components/popper/Overlay.js +++ b/components/popper/Overlay.js @@ -29,7 +29,8 @@ const Overlay = (props) => { onMouseLeave, onClickOutside, overlayClassName, - onKeyDown + onKeyDown, + overlayClickOutSideEventName = 'click' } = props const [isAddevent, setIsAddevent] = useState(false) const [state, setState] = useState({ @@ -52,7 +53,7 @@ const Overlay = (props) => { onClickOutside && onClickOutside(e) }, undefined, - 'click', + overlayClickOutSideEventName, attachEle ) } diff --git a/components/select/Select.js b/components/select/Select.js index d14901757..6004b33a5 100644 --- a/components/select/Select.js +++ b/components/select/Select.js @@ -40,7 +40,8 @@ const InternalSelect = (props) => { fieldNames, overlayClassName, setOverlayContainer, - bordered = true + bordered = true, + overlayClickOutSideEventName = 'click' } = props const selectInputContainer = useRef() const autoloadFlag = useRef(autoload) // 多选情况下,需要记录是否进行了筛选 @@ -129,9 +130,13 @@ const InternalSelect = (props) => { setSelectedItems(selectedItems) if (dataSource && type === 'multiple') { setCacheSelectItem(selectedItems) - !dropdownShow && setDropdownItems(selectedItems) + !dropdownShow && searchable && setDropdownItems(selectedItems) } else { - setDropdownItems(_data) + if (dataSource) { + searchable && setDropdownItems(_data) + } else { + setDropdownItems(_data) + } } }, [data, value]) @@ -449,19 +454,22 @@ const InternalSelect = (props) => { }, []) // 过滤筛选项 - const onFilterItems = (keyword) => { - setKeyword(keyword) - if (typeof onSearch === 'function') { - onSearch(keyword) - return - } - if (dataSource && (autoload || keyword)) { - remoteSearch(keyword) - } - if (dataSource && keyword === '' && selectedItems.length > 0) { - setDropdownItems(cacheSelectItem) - } - } + const onFilterItems = useCallback( + (keyword) => { + setKeyword(keyword) + if (typeof onSearch === 'function') { + onSearch(keyword) + return + } + if (dataSource && (autoload || keyword) && searchable) { + remoteSearch(keyword) + } + if (dataSource && searchable && keyword === '' && selectedItems.length > 0) { + setDropdownItems(cacheSelectItem) + } + }, + [dataSource, cacheSelectItem, keyword, selectedItems, searchable, onSearch, remoteSearch, autoload] + ) // 重置下标 const resetFocusedIndex = () => { let _dropdownItems = dropdownItems || [] @@ -527,7 +535,7 @@ const InternalSelect = (props) => { resetFocusedIndex() }) setCacheSelectItem([]) - dataSource && setDropdownItems([]) + dataSource && searchable && setDropdownItems([]) } // 防抖 const debouncedFilterItems = _.debounce(onFilterItems, 300) @@ -621,6 +629,7 @@ const InternalSelect = (props) => { topGap={5} leftGap={0} overlayClassName={overlayClassName} + overlayClickOutSideEventName={overlayClickOutSideEventName} setOverlayContainer={setOverlayContainer} // 是否防止溢出功能 暂时不开放 preventOverflow={preventOverflow} diff --git a/docs/demo/form/section-schema.jsx b/docs/demo/form/section-schema.jsx index 95598b63f..07fc966e3 100644 --- a/docs/demo/form/section-schema.jsx +++ b/docs/demo/form/section-schema.jsx @@ -9,6 +9,7 @@ import Cascader from '../../../components/cascader' import Radio from '../../../components/radio' import Checkbox from '../../../components/checkbox' import Switch from '../../../components/switch' +import SelectTree from '../../../components/select-tree' import DatePicker from '../../../components/date-picker' import Rate from '../../../components/rate' import Upload from '../../../components/upload' @@ -97,17 +98,20 @@ const code = [ } ] } + this.form = React.createRef() } render () { const SchemaForm = Form.SchemaForm const {initialValues} = this.state return ( +
+ +
+ ) } }` @@ -360,7 +393,8 @@ const DemoRow = () => ( DatePicker, Rate, Upload, - Grid + Grid, + SelectTree }} prefix={prefix} desc={desc} diff --git a/docs/zh-CN/components/form.mdx b/docs/zh-CN/components/form.mdx index d05528ae8..07adf6d33 100755 --- a/docs/zh-CN/components/form.mdx +++ b/docs/zh-CN/components/form.mdx @@ -123,7 +123,7 @@ import DemoUseForm from '../../demo/form/section-useForm.jsx' | 参数 | 说明 | 类型 | 可选值 | 默认值 | | -------------- | ----------------------------------------------------------- | ------ | ------ | ------ | -| component | 用于渲染的组件名称,(现在组件名称,只限于 HiUI 中的组件名) | string | - | - | +| component | 用于渲染的组件名称(现在组件名称,只限于 HiUI 中的组件名);如果传入 **ReactNode** 的情况下,**componentProps** 属性失效,同时也会默认控制组件 **value** 属性| string \| ReactNode | - | - | | componentProps | 组件的属性 | string | - | - | ## Form.Submit @@ -153,6 +153,7 @@ import DemoUseForm from '../../demo/form/section-useForm.jsx' | validateField(fields: string, callback: errors => void) | 对指定表单字段进行校验 | | resetValidates(callback:() => void, fields:Array, toDefault:boolean) | 重置整个表单的验证,对应 [Form.Reset](#Form.Reset)中的 API | | setFieldsValue(field: Object) | 设置表单的值,在异步获取的数据回显的时候,使用该方法 | +| updateSchema( schemaData: {fileName: [SchemaItem](#SchemaItem) } ) => void | 当 **SchemaItem** 中对应的 **schema** 数据更新时,请调用该方法更新 | ## rules