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>
效果
設置對話框確認和取消按鈕的文字
ok-text : 設置確認按鈕文字
cancel-text : 設置取消按鈕文字
例:
<a-modal
title="模態框標題"
ok-text="確認"
cancel-text="取消"
:visible="visible"
:confirm-loading="confirmLoading"
@ok="handleOk"
@cancel="handleCancel"
>
效果
對話框結合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>
效果
注意:這種方式需要支持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>
效果
設置 確認按鈕提交的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.
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]" #
經過
getFieldDecorator
或v-decorator
包裝的控件,表單控件會自動添加value
(或valuePropName
指定的其他屬性)onChange
(或trigger
指定的其他屬性),數據同步將被 Form 接管,這會導致以下結果:
- 你不再需要也不應該用
onChange
來做同步,但還是可以繼續監聽onChange
等事件。- 你不能用控件的
value
defaultValue
等屬性來設置表單域的值,默認值可以用getFieldDecorator
或v-decorator
里的initialValue
。- 你不應該用
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>
效果
注意:雙向綁定切換需要使用字符串的形式,就算是數值也需要,
如:
status : '1'
this.form.status = ''+record.status;
表單驗證 #
Form 組件提供了表單驗證的功能,只需要通過 rules
屬性傳入約定的驗證規則,並將 FormItem
的 prop
屬性設置為需校驗的字段名即可。校驗規則參見 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>
效果