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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM