1. 定义表单项组件

  • 自定义文本输入框
  • 自定义开关选择器
<template>

  <a-input style="width: 100%;" v-model="childVal" @blur="handleChildBlur"></a-input>

</template>

<script>

export default {

  name: "AiKanCustomInput",
  props: {
    fatherVal: String
  },

  // 2.2新增 在组件内定义 指定父组件调用时候的传值属性和事件类型
  model: {
    prop: "fatherVal",
    event: "handleChildValueChange"
  },

  data() {
    return {
      childVal: this.fatherVal
    }
  },

  methods: {
    handleChildBlur() {
      // 通过model属性设置,这样就可以修改父组件v-model绑定的值
      this.$emit("handleChildValueChange", this.childVal);
    }
  }

}

</script>
<template>

  <a-switch v-model="childVal" @change="handleChildSelectChange"/>

</template>

<script>

export default {
  name: "AiKanCustomSwitch",
  props: {
    fatherVal: Boolean,
  },

  // 2.2新增 在组件内定义 指定父组件调用时候的传值属性和事件类型
  model: {
    prop: "fatherVal",
    event: "handleChildValueChange"
  },

  data() {
    return {
      childVal: this.fatherVal
    }
  },

  methods: {
    handleChildSelectChange() {
      // 通过model属性设置,这样就可以修改父组件v-model绑定的值
      this.$emit("handleChildValueChange", this.childVal);
    }
  }

}

</script>

利用model属性,可以让父组件绑定值和子组件绑定值进行双向绑定;做到子组件值变化,父组件值也跟着变化

2. 定义表单并引用表单项组件

<template>

  <a-modal :visible="visible" :title="'动态表单编辑Modal'" :width="1000" @ok="handleSubmit" @cancel="handleCancel">
    <a-form-model ref="form" :model="form">
      <a-form-model-item v-for="field in formFields" :label="field.label" :prop="field.prop" :labelCol="labelCol" :wrapperCol="wrapperCol">
        <component :is="field.componentType" v-model="form[field.prop]" :fatherVal="form[field.prop]"/>
      </a-form-model-item>
    </a-form-model>
  </a-modal>

</template>
<script>
import AiKanCustomInput from "./modules/AiKanCustomInput";
import AiKanCustomSwitch from "./modules/AiKanCustomSwitch";

const form_fields = [
  {
    label: '姓名',
    prop: 'name',
    componentType: 'ai-kan-custom-input'
  },
  {
    label: '是否删除',
    prop: 'delFlag',
    componentType: 'ai-kan-custom-switch'
  }
];


export default {

  name: "AiKanFormModal",
  components: {
    AiKanCustomSwitch,
    AiKanCustomInput
  },

  data() {
    return {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 5 },
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 },
      },
      formFields: form_fields,
      visible: false,
      form: {},
    }
  },

  methods: {
    handleSubmit() {
      console.log("====" + JSON.stringify(this.form));
    },
    handleCancel() {
      this.visible = false;
    },
  }

}
</script>

这样就可以通过定义js对象数组form_fields来动态自定义表单内容
效果如下:

image

当我们提交表单时,form数据也是自动填充了

image

3. 增加表单校验

  1. 模式一,validateRules数据格式如下:
 const validateRules = {
   'name': {required: true, pattern: /^[a-zA-Z]{3,6}$/},
   'delFlag': {required: true},
 };
<template>

  <a-modal :visible="visible" :title="'动态表单编辑Modal'" :width="1000" @ok="handleSubmit" @cancel="handleCancel">
    <a-form-model ref="form" :model="form" :rules="validateRules">
      <a-form-model-item v-for="field in formFields" :label="field.label" :prop="field.prop" :labelCol="labelCol" :wrapperCol="wrapperCol">
        <component :is="field.componentType" v-model="form[field.prop]" :fatherVal="form[field.prop]"/>
      </a-form-model-item>
    </a-form-model>
  </a-modal>

</template>
<script>
import AiKanCustomInput from "./modules/AiKanCustomInput";
import AiKanCustomSwitch from "./modules/AiKanCustomSwitch";

const form_fields = [
  {
    label: '姓名',
    prop: 'name',
    componentType: 'ai-kan-custom-input'
  },
  {
    label: '是否删除',
    prop: 'delFlag',
    componentType: 'ai-kan-custom-switch'
  }
];

const validateRules = {
  'name': {required: true, pattern: /^[a-zA-Z]{3,6}$/},
  'delFlag': {required: true},
};


export default {

  name: "AiKanFormModal",
  components: {
    AiKanCustomSwitch,
    AiKanCustomInput
  },

  data() {
    return {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 5 },
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 },
      },
      formFields: form_fields,
      validateRules: validateRules,
      visible: false,
      form: {},
    }
  },

  methods: {
    handleSubmit() {
      this.$refs.form.validate(valid => {
        if (valid) {
          console.log("====验证成功," + JSON.stringify(this.form));
        } else {
          console.log("====验证失败," + JSON.stringify(this.form));
        }
      })
    },
    handleCancel() {
      this.visible = false;
    },
  }

}
</script>
  1. 模式二,校验规则数据在form_fields里面,则需将rules定义在a-form-model-item上,并编写validateFields对formItem进行验证,格式如下:
const form_fields = [
 {
   label: '姓名',
   prop: 'name',
   componentType: 'ai-kan-custom-input',
   validateRule: {required: true, pattern: /^[a-zA-Z]{3,6}$/}
 },
 {
   label: '是否删除',
   prop: 'delFlag',
   componentType: 'ai-kan-custom-switch',
   validateRule: {required: true}
 }
];
<template>

  <a-modal :visible="visible" :title="'动态表单编辑Modal'" :width="1000" @ok="handleSubmit" @cancel="handleCancel">
    <a-form-model ref="form" :model="form">
      <a-form-model-item v-for="field in formFields" :label="field.label" :prop="field.prop" :labelCol="labelCol" :wrapperCol="wrapperCol" :rules="field.validateRule">
        <component :is="field.componentType" v-model="form[field.prop]" :fatherVal="form[field.prop]"/>
      </a-form-model-item>
    </a-form-model>
  </a-modal>

</template>
<script>
import AiKanCustomInput from "./modules/AiKanCustomInput";
import AiKanCustomSwitch from "./modules/AiKanCustomSwitch";

const form_fields = [
  {
    label: '姓名',
    prop: 'name',
    componentType: 'ai-kan-custom-input',
    validateRule: {required: true, pattern: /^[a-zA-Z]{3,6}$/}
  },
  {
    label: '是否删除',
    prop: 'delFlag',
    componentType: 'ai-kan-custom-switch',
    validateRule: {required: true}
  }
];


export default {

  name: "AiKanFormModal",
  components: {
    AiKanCustomSwitch,
    AiKanCustomInput
  },

  data() {
    return {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 5 },
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 },
      },
      formFields: form_fields,
      visible: false,
      form: {},
    }
  },

  methods: {
    validateFields() {
      let result = true;
      for (let formItem of this.$refs.form.fields) {
        this.$refs.form.validateField(formItem.prop, err => {
          if (err !== "") {
            result = false;
          }
        });
        if (!result) {
          break;
        }
      }
      return result;
    },
    handleSubmit() {
      if (this.validateFields()) {
        console.log("====验证成功," + JSON.stringify(this.form));
      } else {
        console.log("====验证失败," + JSON.stringify(this.form));
      }
    },
    handleCancel() {
      this.visible = false;
    },
  }

}
</script>

效果如下图:
image
image
image
image

posted on 2022-08-24 09:18  Xs007  阅读(417)  评论(0)    收藏  举报