diff --git a/packages/devui-vue/devui/form/index.ts b/packages/devui-vue/devui/form/index.ts index bdbb61bbf6e0ac8c1efc924b0cbf2356d5bf84fa..eaab6cdba3b8debf7846fb0f41b9bac11263e46b 100644 --- a/packages/devui-vue/devui/form/index.ts +++ b/packages/devui-vue/devui/form/index.ts @@ -4,6 +4,7 @@ import FormLabel from './src/form-label/form-label'; import FormItem from './src/form-item/form-item'; import FormControl from './src/form-control/form-control'; import FormOperation from './src/form-operation/form-operation'; +import CrossComponentValidateDemo from './src/cross-component-validate-demo/cross-component-validate-demo'; import dValidateRules from './src/directive/d-validate-rules'; Form.install = function(app: App) { @@ -27,7 +28,11 @@ FormOperation.install = function(app: App) { app.component(FormOperation.name, FormOperation) } -export { Form, FormLabel, FormItem, FormControl, FormOperation } +CrossComponentValidateDemo.install = function(app: App) { + app.component(CrossComponentValidateDemo.name, CrossComponentValidateDemo) +} + +export { Form, FormLabel, FormItem, FormControl, FormOperation, CrossComponentValidateDemo } export default { title: 'Form 表单', @@ -39,5 +44,6 @@ export default { app.use(FormItem as any); app.use(FormControl as any); app.use(FormOperation as any); + app.use(CrossComponentValidateDemo as any); } } diff --git a/packages/devui-vue/devui/form/src/cross-component-validate-demo/cross-component-validate-demo.scss b/packages/devui-vue/devui/form/src/cross-component-validate-demo/cross-component-validate-demo.scss new file mode 100644 index 0000000000000000000000000000000000000000..57aa9c1e402fca1d48b13ec8642e14f57ec6f281 --- /dev/null +++ b/packages/devui-vue/devui/form/src/cross-component-validate-demo/cross-component-validate-demo.scss @@ -0,0 +1,3 @@ +.devui-form-cross-component-validate-demo { + +} diff --git a/packages/devui-vue/devui/form/src/cross-component-validate-demo/cross-component-validate-demo.tsx b/packages/devui-vue/devui/form/src/cross-component-validate-demo/cross-component-validate-demo.tsx new file mode 100644 index 0000000000000000000000000000000000000000..0aecb224bcf568bceb40170545201b3bbdfc61b4 --- /dev/null +++ b/packages/devui-vue/devui/form/src/cross-component-validate-demo/cross-component-validate-demo.tsx @@ -0,0 +1,42 @@ +import { defineComponent, ref, watch } from 'vue'; +import './cross-component-validate-demo.scss'; + +export default defineComponent({ + name: 'CrossComponentValidateDemo', + props: { + age: { + type: [Number, String], + default: 0 + } + }, + emits: ['ageChange'], + setup(props, ctx) { + const ageData = ref(props.age); + + const customAsyncValidator = (rule, value) => { + return value >= 0 && value <= 200; + } + + watch(() => props.age, (newVal) => { + ageData.value = newVal; + }) + + return () => { + return
+ { + ctx.emit('ageChange', val); + }} v-d-validate-rules={{ + rules: { + asyncValidators: [ + {message: '年龄范围必须在0~200之间', asyncValidator: customAsyncValidator} + ] + }, + options: { + updateOn: 'input', + asyncDebounceTime: 500 + } + }} /> +
+ } + } +}) \ No newline at end of file diff --git a/packages/devui-vue/devui/form/src/directive/d-validate-rules.ts b/packages/devui-vue/devui/form/src/directive/d-validate-rules.ts index 87edc1a694b8d03a6e91540add0499e5a5ba0e4c..67388384b01ab1991a6bbf3afb8750b546d81c9b 100644 --- a/packages/devui-vue/devui/form/src/directive/d-validate-rules.ts +++ b/packages/devui-vue/devui/form/src/directive/d-validate-rules.ts @@ -246,7 +246,7 @@ function getRefName(binding: DirectiveBinding): string { function getFormName(binding: DirectiveBinding): string { const _refs = binding.instance.$refs; const key = Object.keys(_refs)[0]; - return _refs[key]['name']; + return _refs[key] ? _refs[key]['name'] : ''; } // 校验处理函数 @@ -277,10 +277,22 @@ function checkValidPopsition(positionStr: string): boolean { return isValid } +// 获取FormControl标签上的uid +function getDfcUID(el: HTMLElement) { + if(el.tagName === "BODY") return ""; + if(el.dataset['uid']) return el.dataset['uid']; + let parent = el.parentElement; + if(parent.dataset['uid']?.startsWith('dfc-')) { + return parent.dataset['uid']; + } else { + return getDfcUID(parent.parentElement); + } +} + export default { mounted(el: HTMLElement, binding: DirectiveBinding, vnode: VNode): void { const isFormTag = el.tagName === 'FORM'; - const dfcUID = el.parentNode.parentNode.parentElement.dataset.uid; + let dfcUID = getDfcUID(el); const refName = getRefName(binding); const hasOptions = isObject(binding.value) && hasKey(binding.value, 'options'); @@ -392,6 +404,9 @@ export default { const validator = new AsyncValidator(descriptor); const htmlEventValidateHandler = (e) => { + // 监听事件的回调函数中需重新获取dfcUID + // 当d-validate-rules指令用在跨组件验证时,因子组件先mounted,这时父组件还未mounted,拿不到父组件的data-uid,所以这里需重新获取dfcUID + dfcUID = getDfcUID(el); const modelValue = e.target.value; if(messageShowType === MessageShowTypeEnum.popover) { EventBus.emit("showPopoverErrorMessage", {showPopover: false, message: "", uid: dfcUID} as ShowPopoverErrorMessageEventData); diff --git a/packages/devui-vue/docs/components/form/index.md b/packages/devui-vue/docs/components/form/index.md index 13591a26d1a139e9b576ffa33b406c67e53d8e10..7d7e823d61898074043f0e42687a9e5607c5ec8b 100644 --- a/packages/devui-vue/docs/components/form/index.md +++ b/packages/devui-vue/docs/components/form/index.md @@ -1502,28 +1502,33 @@ export default defineComponent({ ### 跨组件验证 -> todo +> done +可以在子组件的数据录入类组件中使用`v-d-validate-rules`指令进行表单验证。 :::demo ```vue @@ -1532,15 +1537,30 @@ import {defineComponent, reactive, ref} from 'vue'; export default defineComponent({ setup(props, ctx) { - const dFormWithComponent = ref(null); + const dFormCrossComponentValidate = ref(null); let formModel = reactive({ name: 'AlanLee', - age: '24', + age: 24, }); + const resetForm = () => { + dFormCrossComponentValidate.value.resetFormFields(); + } + + const onSubmit = (e) => { + console.log('@submit', formModel); + } + + const onAgeChange = val => { + formModel.age = val; + } + return { - dFormWithComponent, + dFormCrossComponentValidate, formModel, + resetForm, + onSubmit, + onAgeChange } } }) @@ -1556,6 +1576,52 @@ export default defineComponent({ } + + + ``` :::