赞
踩
首先我们先看一下官网给出的示例:
点击Add filed 会增加一个新的input输入框
点击删除的时候可以删除该行input框
下面给出官网的demo示例:
<template> <a-form :form="form" @submit="handleSubmit"> <a-form-item v-for="(k, index) in form.getFieldValue('keys')" :key="k" v-bind="index === 0 ? formItemLayout : formItemLayoutWithOutLabel" :label="index === 0 ? 'Passengers' : ''" :required="false" > <a-input v-decorator="[ `names[${k}]`, { validateTrigger: ['change', 'blur'], rules: [ { required: true, whitespace: true, message: 'Please input passenger\'s name or delete this field.', }, ], }, ]" placeholder="passenger name" style="width: 60%; margin-right: 8px" /> <a-icon v-if="form.getFieldValue('keys').length > 1" class="dynamic-delete-button" type="minus-circle-o" :disabled="form.getFieldValue('keys').length === 1" @click="() => remove(k)" /> </a-form-item> <a-form-item v-bind="formItemLayoutWithOutLabel"> <a-button type="dashed" style="width: 60%" @click="add"> <a-icon type="plus" /> Add field </a-button> </a-form-item> <a-form-item v-bind="formItemLayoutWithOutLabel"> <a-button type="primary" html-type="submit"> Submit </a-button> </a-form-item> </a-form> </template> <script> let id = 0; export default { data() { return { formItemLayout: { labelCol: { xs: { span: 24 }, sm: { span: 4 }, }, wrapperCol: { xs: { span: 24 }, sm: { span: 20 }, }, }, formItemLayoutWithOutLabel: { wrapperCol: { xs: { span: 24, offset: 0 }, sm: { span: 20, offset: 4 }, }, }, }; }, beforeCreate() { this.form = this.$form.createForm(this, { name: 'dynamic_form_item' }); this.form.getFieldDecorator('keys', { initialValue: [], preserve: true }); }, methods: { remove(k) { const { form } = this; // can use data-binding to get const keys = form.getFieldValue('keys'); // We need at least one passenger if (keys.length === 1) { return; } // can use data-binding to set form.setFieldsValue({ keys: keys.filter(key => key !== k), }); }, add() { const { form } = this; // can use data-binding to get const keys = form.getFieldValue('keys'); const nextKeys = keys.concat(id++); // can use data-binding to set // important! notify form to detect changes form.setFieldsValue({ keys: nextKeys, }); }, handleSubmit(e) { e.preventDefault(); this.form.validateFields((err, values) => { if (!err) { const { keys, names } = values; console.log('Received values of form: ', values); console.log( 'Merged values:', keys.map(key => names[key]), ); } }); }, }, }; </script> <style> .dynamic-delete-button { cursor: pointer; position: relative; top: 4px; font-size: 24px; color: #999; transition: all 0.3s; } .dynamic-delete-button:hover { color: #777; } .dynamic-delete-button[disabled] { cursor: not-allowed; opacity: 0.5; } </style>
我们分析官网给出的demo,可以知道整个表单的重点构成在于:
遍历form表单中keys数组,为form-item赋予不同的key,紧接着生成a-input
所以我们也可以推测出,进行动态的动态增加、减少表单项的关键在于操作keys数组。
我们在通过v-decorator为input绑定数据源时,需要使用names[${k}],如下图所示:
我们在表单构建之前使用生命周期beforeCreate,首先使用createForm创建表单,然后为表单的keys设置初始值为空数组,并且设置keys是保留项。
在remove和add方法中主要是操作keys数组的变化,然后通过setFieldsValue设置keys的值。
例如:
form.setFieldsValue({
keys: keys.filter(key => key !== k),
});
到这里官网示例可以满足我们大部分需求,但是在使用接口数据动态的加载表单的时候,因为异步问题会存在一些问题。下面我将会为大家解答这些问题。
废话不多说先上代码:
<template> <a-form :form="form" > <template v-if="show"> <a-form-item v-for="(key, index) in form.getFieldValue('keys')" :key="key" :label="`${index+1}WHY`" > <a-input v-decorator="[ `names[${key}]`, { }]" /> </a-form-item> <a-form-item :label="'test'" > <a-input v-decorator="[ `test`, { }]" /> </a-form-item> </template> </a-form> </template> </template> <script> export default { data () { return { show: false, }; }, beforeCreate () { this.form = this.$form.createForm(this); // 通过setTimeout模拟网络请求 setTimeout((res) => { this.form.getFieldDecorator('keys', { initialValue: res.keys, preserve: true }); this.show = true; this.$nextTick(() => { this.form.setFieldsValue(res); }); }, 2000, { keys: [0, 1, 2, 3], names: ['窗前明月光', '疑似地上霜', '举头望明月', '低头思故乡'], test: 'test' }); }, }; </script>
我们使用setTimeout模拟网络请求,来实现模仿异步请求生成动态表单。
其中需要注意的是:
1、我们需要先将表单设置为隐藏状态,在接口返回数据之后,设置表单为显示状态。
2、我们使用setFieldsValue设置表单的显示值时,需要使用nextTick,否则无法设置成功。
3、另外需要注意的一点时,keys数组必须从0开始。
运行结果:
注解:
1、如果你在使用的过程中遇到了,第一个input框无法赋值的时候,可以尝试单独设置第一个input框的v-decorator的names[0]改为下标非0的值。
例如:this.form.setFieldsValue({ ‘names[11]’: res[0].whyDescription });
2、如果你在生命周期中设置了names的初始值,例如:
this.form.getFieldDecorator(‘names’, { initialValue: [], preserve: false });
那么每次刷新的表单的时候都会把默认值设置成空,如果不需要此功能,请删除此行代码。
参考文档:https://www.jianshu.com/p/a22604f88f3b
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。