ant design vue Modal 对话框和表单的使用

https://www.antdv.com/components/modal-cn/

对话框基本使用

<template>
    <div>
        <a-button type="primary" @click="showModal">
            显示模态框
        </a-button>
        <a-modal
                title="模态框标题"
                :visible="visible"
                :confirm-loading="confirmLoading"
                @ok="handleOk"
                @cancel="handleCancel"
        >
            <p>{{ ModalText }}</p>
        </a-modal>
    </div>
</template>
<script>
    export default {
        data() {
            return {
                ModalText: 'Content of the modal',
                visible: false,
                confirmLoading: false,
            };
        },
        methods: {
            //显示模态框
            showModal() {
                this.visible = true;
            },
            //点击ok
            handleOk(e) {
                this.ModalText = 'The modal will be closed after two seconds';
                this.confirmLoading = true;
                setTimeout(() => {
                    this.visible = false;
                    this.confirmLoading = false;
                }, 2000);
            },
            //点击cancel
            handleCancel(e) {
                console.log('Clicked cancel button');
                this.visible = false;
            },
        },
    };
</script>

效果

image-20201117143920500

设置对话框确认和取消按钮的文字

ok-text : 设置确认按钮文字
cancel-text : 设置取消按钮文字

例:

<a-modal
        title="模态框标题"
        ok-text="确认" 
        cancel-text="取消"
        :visible="visible"
        :confirm-loading="confirmLoading"
        @ok="handleOk"
        @cancel="handleCancel"
>

效果

image-20201117144235123

对话框结合form表单使用

https://www.antdv.com/components/form-cn/#components-form-demo-form-in-modal-to-create

方式1:自定义组件模板的方式

<template>
    <div>
        <a-button type="primary" @click="showModal">
            显示模态框
        </a-button>
        <collection-create-form
                ref="collectionForm"
                :visible="visible"
                @cancel="handleCancel"
                @create="handleCreate"
        />
    </div>
</template>

<script>
    const CollectionCreateForm = {
        props: ['visible'],
        beforeCreate() {
            this.form = this.$form.createForm(this, { name: 'form_in_modal' });
        },
        template: `
            <a-modal
                    :visible="visible"
                    title='模态框标题'
                    okText='确认'
                    cancel-text="取消"
                    @cancel="() => { $emit('cancel') }"
                    @ok="() => { $emit('create') }"
            >
                <a-form layout='vertical' :form="form">
                    <a-form-item label='Title'>
                        <a-input
                                v-decorator="[
                                      'title',
                                      {
                                        rules: [{ required: true, message: 'title必填!' }],
                                      }
                                ]"
                        />
                    </a-form-item>
                    <a-form-item label='Description'>
                        <a-input
                                type='textarea'
                                v-decorator="['description']"
                        />
                    </a-form-item>
                    <a-form-item class='collection-create-form_last-form-item'>
                        <a-radio-group
                                v-decorator="[
                                  'modifier',
                                      {
                                        initialValue: 'private',
                                      }
                                ]"
                        >
                            <a-radio value='public'>Public</a-radio>
                            <a-radio value='private'>Private</a-radio>
                        </a-radio-group>
                    </a-form-item>
                </a-form>
            </a-modal>
        `,
    };

    export default {
        components: { CollectionCreateForm },
        data() {
            return {
                visible: false,
            };
        },
        methods: {
            //显示模态框
            showModal() {
                this.visible = true;
            },
            //关闭模态框
            handleCancel() {
                this.visible = false;
            },
            //点击确认
            handleCreate() {
                const form = this.$refs.collectionForm.form;
                form.validateFields((err, values) => {
                    if (err) {
                        return;
                    }
                    console.log('form 表单内容: ', values);
                    form.resetFields();
                    this.visible = false;
                });
            },
        },
    };
</script>

效果

image-20201117155754749

注意:这种方式需要支持template选项

报错参考:https://www.cnblogs.com/makalochen/p/13994493.html

方式二:组件绑定form

<template>
    <div>
        <!--添加按钮和模态框-->
        <a-button type="primary" @click="showModal">
            添加
        </a-button>
        <a-modal
                :visible="visible"
                :title= "modelTitle"
                okText='确认'
                cancel-text="取消"
                @cancel="handleCancel"
                @ok="handleOk"
        >
            <!--表单 并将表单的值绑定到this.from-->
            <a-form layout='vertical' :form="form">
                <!--每一项元素-->
                <a-form-item label='用户名'>
                    <a-input
                            v-decorator="[
                                      'username',
                                      {
                                        rules: [{ required: true, message: '请填写登录用户名!' }],
                                      }
                                ]"
                    />
                </a-form-item>
                <a-form-item label='密码'>
                    <a-input
                            type='password'
                            v-decorator="[
                                      'password',
                                      {
                                        rules: [{ required: true, message: '请填写登录密码!' }],
                                      }
                                ]"
                    />
                </a-form-item>
                <a-form-item label="状态">
                    <a-radio-group
                            v-decorator="[
                                  'status',
                                      {
                                        initialValue: '1',
                                      }
                                ]"
                    >
                        <a-radio value='1'>启用</a-radio>
                        <a-radio value='0'>禁用</a-radio>
                    </a-radio-group>
                </a-form-item>
            </a-form>
        </a-modal>
    </div>
</template>

<script>
    export default {
        //el 创建前
        beforeCreate() {
            //创建表单
            this.form = this.$form.createForm(this, { name: 'form_in_modal' });
        },
        data() {
            return {
                visible: false,
                //模态对话框标题
                modelTitle: '模态框标题',
            };
        },
        methods: {
            //显示模态框
            showModal() {
                this.visible = true;
            },
            //关闭模态框
            handleCancel() {
                this.visible = false;
            },
            //点击确认
            handleOk() {
                const form = this.form;
                form.validateFields((err, values) => {
                    if (err) {
                        return;
                    }
                    console.log('form 表单内容: ', values);
                    form.resetFields();
                    this.visible = false;
                });
            },
        },
    };
</script>

效果

image-20201117175623176

设置 确认按钮提交的loading

例:

组件设置
<!--对话框-->
<a-modal
        :visible="visible"
        :title= "modelTitle"
        :confirm-loading="confirmLoading"
        okText='确认'
        cancel-text="取消"
        @cancel="handleCancel"
        @ok="add"
>

data() 设置
//true表示loading,反之则使用false
confirmLoading: false,   

设置model的表单项

//设置模态框的form表单的值
this.$nextTick(()=>{
    setTimeout(() => {
        this.form.setFieldsValue({
            username : record.username,
            password : record.password,
            status : record.status
        });
    })
})

设置表单项报错的问题

Warning: You cannot set a form field before rendering a field associated with the value.

image-20201117190428011

https://www.cnblogs.com/cirry/p/12483131.html

在用ant-design-vue的框架中,使用到了这种场景,就是点击编辑按钮,弹出modal模态框,渲染modal模态框中的form表单页面,并给表单赋值,但是在给表单赋值的时候,总是会报错。

错误提示: Warning: You cannot set a form field before rendering a field associated with the value.

经过一番查找后发现,造成这种原因一般有以下几个原因:

1.使用了表单的方法setFieldsValue(),来设置一组输入控件的值,传入的值为object,但是传入的值要和表单的值一一对应,能少传不能多传。

遇到这种情况的解决方式为:form渲染需要什么值你就传什么值

方式1:一个一个传

 this.form.setFieldsValue({ note: '123', mark: '456' })

方式2:

add (record) {  //record:需要引用的值
   this.visible = true
   this.mdl = Object.assign({}, record)  // 浅拷贝
   this.form.setFieldsValue(pick(this.mdl, 'note', 'mark'))  // loadsh的pick方法
}

但是你会发现这么些还是报同样的错误。按照错误提示的原意:不能在表单渲染之前赋值

2.调用setFieldsValue()方法,需要放在$nextTick()函数中执行,改为如下即可:

this.$nextTick(()=>{
    this.form.setFieldsValue(pick(this.mdl, 'note', 'mark'))  // loadsh的pick方法
})

一般到这里就能解决问题了,如果还在报同样的错误,那就这样吧:

3.再放到setTimeout()方法中

this.$nextTick(() => {
     setTimeout(() => {
     this.form.setFieldsValue(pick(this.mdl, 'note', 'mark'))  // loadsh的pick方法
     })
})

关于form表单使用v-decorator绑定了默认值不能修改的问题

this.form.getFieldDecorator(id, options) 和 v-decorator="[id, options]" #

经过 getFieldDecoratorv-decorator 包装的控件,表单控件会自动添加 value(或 valuePropName 指定的其他属性) onChange(或 trigger 指定的其他属性),数据同步将被 Form 接管,这会导致以下结果:

  1. 不再需要也不应该onChange 来做同步,但还是可以继续监听 onChange 等事件。
  2. 你不能用控件的 value defaultValue 等属性来设置表单域的值,默认值可以用 getFieldDecoratorv-decorator 里的 initialValue
  3. 你不应该用 v-model,可以使用 this.form.setFieldsValue 来动态改变表单值。

使用form表单是不能修改的,推荐使用FormModel表单,而且v2版本也移除了form表单,保留了formModel表单:

https://2x.antdv.com/docs/vue/migration-v2-cn/

组件重构 #

在 1.x 中我们提供了 Form、FormModel 两个表单组件,原有的 Form 组件使用 v-decorator 进行数据绑定,在 Vue2 中我们通过上下文进行强制更新组件,但是在 Vue3 中,由于引入 patchFlag 等优化方式,强制刷新会破坏 patchFlag 带来的性能优势。所以在 2.0 版本中我们将 Form、FormModel 进行合并,保留了 FormModel 的使用方式,丰富了相关功能,并改名成 Form。

FormModel表单使用

FormModel表单: https://www.antdv.com/components/form-model-cn/

基本使用:

<template>
    <a-form-model :model="form" :label-col="labelCol" :wrapper-col="wrapperCol">
        <a-form-model-item label="Activity name">
            <a-input v-model="form.name" />
        </a-form-model-item>
        <a-form-model-item label="Activity zone">
            <a-select v-model="form.region" placeholder="please select your zone">
                <a-select-option value="shanghai">
                    Zone one
                </a-select-option>
                <a-select-option value="beijing">
                    Zone two
                </a-select-option>
            </a-select>
        </a-form-model-item>
        <a-form-model-item label="Activity time">
            <a-date-picker
                    v-model="form.date1"
                    show-time
                    type="date"
                    placeholder="Pick a date"
                    style="width: 100%;"
            />
        </a-form-model-item>
        <a-form-model-item label="Instant delivery">
            <a-switch v-model="form.delivery" />
        </a-form-model-item>
        <a-form-model-item label="Activity type">
            <a-checkbox-group v-model="form.type">
                <a-checkbox value="1" name="type">
                    Online
                </a-checkbox>
                <a-checkbox value="2" name="type">
                    Promotion
                </a-checkbox>
                <a-checkbox value="3" name="type">
                    Offline
                </a-checkbox>
            </a-checkbox-group>
        </a-form-model-item>
        <a-form-model-item label="Resources">
            <a-radio-group v-model="form.resource">
                <a-radio value="1">
                    Sponsor
                </a-radio>
                <a-radio value="2">
                    Venue
                </a-radio>
            </a-radio-group>
        </a-form-model-item>
        <a-form-model-item label="Activity form">
            <a-input v-model="form.desc" type="textarea" />
        </a-form-model-item>
        <a-form-model-item :wrapper-col="{ span: 14, offset: 4 }">
            <a-button type="primary" @click="onSubmit">
                Create
            </a-button>
            <a-button style="margin-left: 10px;">
                Cancel
            </a-button>
        </a-form-model-item>
    </a-form-model>
</template>
<script>
    export default {
        data() {
            return {
                labelCol: { span: 4 },
                wrapperCol: { span: 14 },
                form: {
                    name: '',
                    region: undefined,
                    date1: undefined,
                    delivery: false,
                    type: [],
                    resource: '',
                    desc: '',
                },
            };
        },
        methods: {
            onSubmit() {
                console.log('submit!', this.form);
            },
        },
    };
</script>

效果

image-20201119110915605

注意:双向绑定切换需要使用字符串的形式,就算是数值也需要,

如:

status : '1'
this.form.status = ''+record.status;

表单验证 #

Form 组件提供了表单验证的功能,只需要通过 rules 属性传入约定的验证规则,并将 FormItemprop 属性设置为需校验的字段名即可。校验规则参见 async-validator

<template>
    <a-form-model
            ref="ruleForm"
            :model="form"
            :rules="rules"
            :label-col="labelCol"
            :wrapper-col="wrapperCol"
    >
        <a-form-model-item ref="name" label="Activity name" prop="name">
            <a-input
                    v-model="form.name"
                    @blur="
          () => {
            $refs.name.onFieldBlur();
          }
        "
            />
        </a-form-model-item>
        <a-form-model-item label="Activity zone" prop="region">
            <a-select v-model="form.region" placeholder="please select your zone">
                <a-select-option value="shanghai">
                    Zone one
                </a-select-option>
                <a-select-option value="beijing">
                    Zone two
                </a-select-option>
            </a-select>
        </a-form-model-item>
        <a-form-model-item label="Activity time" required prop="date1">
            <a-date-picker
                    v-model="form.date1"
                    show-time
                    type="date"
                    placeholder="Pick a date"
                    style="width: 100%;"
            />
        </a-form-model-item>
        <a-form-model-item label="Instant delivery" prop="delivery">
            <a-switch v-model="form.delivery" />
        </a-form-model-item>
        <a-form-model-item label="Activity type" prop="type">
            <a-checkbox-group v-model="form.type">
                <a-checkbox value="1" name="type">
                    Online
                </a-checkbox>
                <a-checkbox value="2" name="type">
                    Promotion
                </a-checkbox>
                <a-checkbox value="3" name="type">
                    Offline
                </a-checkbox>
            </a-checkbox-group>
        </a-form-model-item>
        <a-form-model-item label="Resources" prop="resource">
            <a-radio-group v-model="form.resource">
                <a-radio value="1">
                    Sponsor
                </a-radio>
                <a-radio value="2">
                    Venue
                </a-radio>
            </a-radio-group>
        </a-form-model-item>
        <a-form-model-item label="Activity form" prop="desc">
            <a-input v-model="form.desc" type="textarea" />
        </a-form-model-item>
        <a-form-model-item :wrapper-col="{ span: 14, offset: 4 }">
            <a-button type="primary" @click="onSubmit">
                Create
            </a-button>
            <a-button style="margin-left: 10px;" @click="resetForm">
                Reset
            </a-button>
        </a-form-model-item>
    </a-form-model>
</template>
<script>
    export default {
        data() {
            return {
                labelCol: { span: 4 },
                wrapperCol: { span: 14 },
                other: '',
                form: {
                    name: '',
                    region: undefined,
                    date1: undefined,
                    delivery: false,
                    type: [],
                    resource: '',
                    desc: '',
                },
                rules: {
                    name: [
                        { required: true, message: 'Please input Activity name', trigger: 'blur' },
                        { min: 3, max: 5, message: 'Length should be 3 to 5', trigger: 'blur' },
                    ],
                    region: [{ required: true, message: 'Please select Activity zone', trigger: 'change' }],
                    date1: [{ required: true, message: 'Please pick a date', trigger: 'change' }],
                    type: [
                        {
                            type: 'array',
                            required: true,
                            message: 'Please select at least one activity type',
                            trigger: 'change',
                        },
                    ],
                    resource: [
                        { required: true, message: 'Please select activity resource', trigger: 'change' },
                    ],
                    desc: [{ required: true, message: 'Please input activity form', trigger: 'blur' }],
                },
            };
        },
        methods: {
            onSubmit() {
                this.$refs.ruleForm.validate(valid => {
                    if (valid) {
                        alert('submit!');
                    } else {
                        console.log('error submit!!');
                        return false;
                    }
                });
            },
            resetForm() {
                this.$refs.ruleForm.resetFields();
            },
        },
    };
</script>

效果

image-20201119113357626

posted @ 2020-11-17 18:14  makalo  阅读(33208)  评论(1编辑  收藏  举报