Browse Source

feat(form): validator 支持回传rule, 用以在自定义 validator 时获得配置在rule的属性来处理不同的逻辑, 含自定义属性 (#1695)

* feat: validator 支持回传rule, 用以在自定义 validator 时获得配置在rule的属性来处理不同的逻辑, 含自定义属性

* feat: demo
Amumu 3 years ago
parent
commit
68049f2b93

+ 10 - 8
src/packages/__VUE/form/common.ts

@@ -1,4 +1,4 @@
-import { getPropByPath, isFunction, isObject, isPromise } from '@/packages/utils/util';
+import { getPropByPath, isObject, isPromise } from '@/packages/utils/util';
 import { computed, provide, reactive, VNode, watch } from 'vue';
 import { FormItemRule } from '../formitem/types';
 import { ErrorMessage, FormRule } from './types';
@@ -78,13 +78,15 @@ export const component = {
         console.warn('[NutUI] <FormItem> 使用 rules 校验规则时 , 必须设置 prop 参数');
       }
 
-      let value = getPropByPath(props.modelValue, prop || '');
+      const value = getPropByPath(props.modelValue, prop || '');
 
       // clear tips
       tipMessage({ prop, message: '' });
-      let _rules = [...rules];
+      const _rules = [...rules];
       while (_rules.length) {
-        const { required, validator, regex, message } = _rules.shift() as FormItemRule;
+        const rule = _rules.shift() as FormItemRule;
+        const { validator, ...ruleWithoutValidator } = rule;
+        const { required, regex, message } = ruleWithoutValidator;
         const errorMsg = { prop, message };
         if (required) {
           if (value === '' || value === undefined || value === null) {
@@ -95,7 +97,7 @@ export const component = {
           return _Promise(errorMsg);
         }
         if (validator) {
-          const result = validator(value);
+          const result = validator(value, ruleWithoutValidator);
           if (isPromise(result)) {
             return new Promise((r, j) => {
               result.then((res) => {
@@ -122,11 +124,11 @@ export const component = {
      * @param customProp 指定校验,用于用户自定义场景时触发,例如 blur、change 事件
      * @returns
      */
-    const validate = (customProp: string = '') => {
+    const validate = (customProp = '') => {
       return new Promise((resolve, reject) => {
-        let task = findFormItem(slots.default());
+        const task = findFormItem(slots.default());
 
-        let errors = task.map((item) => {
+        const errors = task.map((item) => {
           if (customProp) {
             if (customProp == item.prop) {
               return checkRule(item);

+ 6 - 0
src/packages/__VUE/form/demo.vue

@@ -79,6 +79,7 @@
         :rules="[
           { required: true, message: translate('ageTip') },
           { validator: customValidator, message: translate('ageTip2') },
+          { validator: customRulePropValidator, message: translate('ageTip2'), reg: /^\d+$/ },
           { regex: /^(\d{1,2}|1\d{2}|200)$/, message: translate('ageTip3') }
         ]"
       >
@@ -168,6 +169,7 @@ import { reactive, ref } from 'vue';
 import { createComponent } from '@/packages/utils/create';
 const { createDemo, translate } = createComponent('form');
 import { useTranslate } from '@/sites/assets/util/useTranslate';
+import { FormItemRuleWithoutValidator } from '../formitem/types';
 const initTranslate = () =>
   useTranslate({
     'zh-CN': {
@@ -391,6 +393,9 @@ export default createDemo({
     };
     // 函数校验
     const customValidator = (val: string) => /^\d+$/.test(val);
+    const customRulePropValidator = (val: string, rule: FormItemRuleWithoutValidator) => {
+      return (rule?.reg as RegExp).test(val);
+    };
     // Promise 异步校验
     const asyncValidator = (val: string) => {
       return new Promise((resolve) => {
@@ -406,6 +411,7 @@ export default createDemo({
       formData,
       validate,
       customValidator,
+      customRulePropValidator,
       asyncValidator,
       customBlurValidate,
       submit,

+ 5 - 1
src/packages/__VUE/form/doc.en-US.md

@@ -138,6 +138,7 @@ export default {
   <nut-form-item label="Age" prop="age" required :rules="[
       { required: true, message: 'Please enter age' },
       { validator: customValidator, message: 'You must enter a number' },
+      { validator: customRulePropValidator, message: 'You must enter a number', reg: /^\d+$/ },
       { regex: /^(\d{1,2}|1\d{2}|200)$/, message: 'The range 0-200 must be entered' }
     ]">
     <input class="nut-input-text" v-model="formData.age" placeholder="Please enter the age, which must be numeric and in the range of 0-200" type="text" />
@@ -196,6 +197,9 @@ setup(){
     };
 
     const customValidator = (val: string) => /^\d+$/.test(val);
+    const customRulePropValidator = (val: string, rule: FormItemRuleWithoutValidator) => {
+      return (rule?.reg as RegExp).test(val);
+    };
     // Promise async validator
     const asyncValidator = (val: string) => {
       return new Promise((resolve) => {
@@ -206,7 +210,7 @@ setup(){
         }, 1000);
       });
     };
-    return { ruleForm, formData, validate, customValidator, asyncValidator, customBlurValidate, submit, reset };
+    return { ruleForm, formData, validate, customValidator, customRulePropValidator, asyncValidator, customBlurValidate, submit, reset };
 }
 }
 </script>

+ 5 - 1
src/packages/__VUE/form/doc.md

@@ -138,6 +138,7 @@ export default {
   <nut-form-item label="年龄" prop="age" required :rules="[
       { required: true, message: '请填写年龄' },
       { validator: customValidator, message: '必须输入数字' },
+      { validator: customRulePropValidator, message: '必须输入数字', reg: /^\d+$/ },
       { regex: /^(\d{1,2}|1\d{2}|200)$/, message: '必须输入0-200区间' }
     ]">
     <input class="nut-input-text" v-model="formData.age" placeholder="请输入年龄,必须数字且0-200区间" type="text" />
@@ -196,6 +197,9 @@ setup(){
     };
     // 函数校验
     const customValidator = (val: string) => /^\d+$/.test(val);
+    const customRulePropValidator = (val: string, rule: FormItemRuleWithoutValidator) => {
+      return (rule?.reg as RegExp).test(val);
+    };
     // Promise 异步校验
     const asyncValidator = (val: string) => {
       return new Promise((resolve) => {
@@ -206,7 +210,7 @@ setup(){
         }, 1000);
       });
     };
-    return { ruleForm, formData, validate, customValidator, asyncValidator, customBlurValidate, submit, reset };
+    return { ruleForm, formData, validate, customValidator, customRulePropValidator, asyncValidator, customBlurValidate, submit, reset };
 }
 }
 </script>

+ 6 - 2
src/packages/__VUE/formitem/types.ts

@@ -1,6 +1,10 @@
-export class FormItemRule {
+export class FormItemRuleWithoutValidator {
   regex?: RegExp;
   required?: boolean;
   message!: string;
-  validator?: (value: any) => boolean | string | Promise<boolean | string>;
+  [key: string]: any;
+}
+
+export class FormItemRule extends FormItemRuleWithoutValidator {
+  validator?: (value: any, ruleCfg: FormItemRuleWithoutValidator) => boolean | string | Promise<boolean | string>;
 }

+ 6 - 0
src/sites/mobile-taro/vue/src/dentry/pages/form/index.vue

@@ -60,6 +60,7 @@
         :rules="[
           { required: true, message: '请填写年龄' },
           { validator: customValidator, message: '必须输入数字' },
+          { validator: customRulePropValidator, message: '必须输入数字', reg: /^\d+$/ },
           { regex: /^(\d{1,2}|1\d{2}|200)$/, message: '必须输入0-200区间' }
         ]"
       >
@@ -148,6 +149,7 @@
 
 <script lang="ts">
 import { reactive, ref } from 'vue';
+import { FormItemRuleWithoutValidator } from '@/packages/__VUE/formitem/types';
 export default {
   props: {},
   setup() {
@@ -289,6 +291,9 @@ export default {
     };
     // 函数校验
     const customValidator = (val: string) => /^\d+$/.test(val);
+    const customRulePropValidator = (val: string, rule: FormItemRuleWithoutValidator) => {
+      return (rule?.reg as RegExp).test(val);
+    };
     // Promise 异步校验
     const asyncValidator = (val: string) => {
       return new Promise((resolve) => {
@@ -304,6 +309,7 @@ export default {
       formData,
       validate,
       customValidator,
+      customRulePropValidator,
       asyncValidator,
       customBlurValidate,
       submit,