# 弹窗表单配置
TIP
表格中的弹出的表单是内置组件avue-form
组件,配置属性可以参考FORM组件文档
# 默认值
配置value
为字段默认值
<avue-crud :option="option" :data="data" ></avue-crud>
<script>
export default{
data() {
return {
data: [],
option: {
height:100,
column: [
{
label: '姓名',
prop: 'name',
value:'small'
}
]
}
}
}
}
</script>
# 打开表单前
TIP
你可以在打开前和关闭前做一些逻辑操作,例如打开根据id请求数据,关闭根据id保存数据等
打开表单前会执行beforeOpen
方法,相关返回的方法值可以判断表单当前打开的类型是新增还是编辑
<avue-crud
:data="data"
v-model="form"
:before-open="beforeOpen"
:option="option"
></avue-crud>
<script>
export default {
data() {
return {
form:{},
data: [{
name:'张三',
sex:'男'
}],
option:{
column:[
{
label:'姓名',
prop:'name'
}, {
label:'性别',
prop:'sex'
}
]
},
};
},
methods: {
beforeOpen(done,type){
this.$alert(`我是${type}`, {
confirmButtonText: '确定',
callback: action => {
if(['view','edit'].includes(type)){
// 查看和编辑逻辑
}else{
//新增逻辑
this.form.name='初始化赋值'
}
done();
}
});
}
}
};
</script>
# 关闭表单前
关闭表单前会执行beforeClose
方法,执行返回的done
方法后才会彻底关闭表单
<avue-crud
:data="data"
v-model="form"
:before-close="beforeClose"
:option="option"
></avue-crud>
<script>
export default {
data() {
return {
form:{},
data: [{
name:'张三',
sex:'男'
}],
option:{
column:[
{
label:'姓名',
prop:'name'
}, {
label:'性别',
prop:'sex'
}
]
},
};
},
methods: {
beforeClose(done,type){
this.$confirm('确认关闭?')
.then(_ => {
done();
})
.catch(_ => {});
}
}
};
</script>
# 不关弹窗连续添加
利用这2个函数可以做不关弹窗连续添加的例子
<avue-crud
ref="crud"
:data="data"
v-model="form"
@row-save="rowSave"
:before-open="beforeOpen"
:before-close="beforeClose"
:option="option"
>
<template slot-scope="{row,index}" slot="menuForm">
<el-button type="primary"
icon="el-icon-check"
size="small"
plain
v-if="type=='add'"
@click="handleNext()"
>继续添加</el-button>
</template>
</avue-crud>
<script>
export default {
data() {
return {
form:{},
flag:false,
type:'',
data: [],
option:{
align:'center',
menuAlign:'center',
viewBtn:true,
column:[
{
label:'姓名',
prop:'name'
}, {
label:'性别',
prop:'sex'
}
]
},
};
},
methods: {
handleNext(){
this.flag=true;
this.$refs.crud.rowSave()
},
rowSave(form,done,loading){
this.data.push(this.deepClone(this.form))
this.$message.success(JSON.stringify(this.form))
if(this.flag){
this.flag=false;
loading()
this.form.name="";
this.form.sex="";
return
}
done()
},
beforeClose(done){
this.flag=false;
done()
},
beforeOpen(done,type){
this.type=type;
done()
}
}
};
</script>
# 表单按钮位置
TIP
2.3.3+
配置dialogMenuPosition
属性值即可,默认为right
<el-radio-group v-model="direction">
<el-radio label="left">居左</el-radio>
<el-radio label="center">居中</el-radio>
<el-radio label="right">居右</el-radio>
</el-radio-group>
<br/><br/>
<avue-crud :option="option" :data="list"></avue-crud>
<script>
export default {
watch:{
direction(value){
this.option.dialogMenuPosition=value;
}
},
data(){
return {
direction:'right',
list:[{
id:1,
name:'张三',
sex:12
},{
id:2,
name:'李四',
sex:12
}],
option:{
dialogMenuPosition:'right',
column:[{
label:'id',
prop:'id'
},{
label:'姓名',
prop:'name'
},{
label:'年龄',
prop:'sex'
}]
}
}
}
}
</script>
# 打开表单方式
TIP
2.1.0+
配置dialogType
为弹窗的方式,dialogDirection
为弹窗的位置
<el-radio-group v-model="direction">
<el-radio label="ltr">从左往右开</el-radio>
<el-radio label="rtl">从右往左开</el-radio>
<el-radio label="ttb">从上往下开</el-radio>
<el-radio label="btt">从下往上开</el-radio>
</el-radio-group>
<br/><br/>
<avue-crud :option="option" :data="list"></avue-crud>
<script>
export default {
watch:{
direction(value){
this.option.dialogDirection=value;
}
},
data(){
return {
direction:'rtl',
list:[{
name:'张三',
sex:12
},{
name:'李四',
sex:12
}],
option:{
dialogDirection:'rtl',
dialogType:'drawer',
column:[{
label:'姓名',
prop:'name'
},{
label:'年龄',
prop:'sex'
}]
}
}
}
}
</script>
# 防重提交
为了防止数据重复提交,加入了防重提交机制,rowSave
方法和rowUpdate
方法返回done
用于关闭表单方法和loading
用于关闭禁止的表单不关闭表单
<avue-crud :data="data" :option="option" @row-save="handleRowSave" @row-update="handleRowUpdate"></avue-crud>
<script>
export default {
data() {
return {
data: [
{
name:'张三',
sex:'男'
}, {
name:'李四',
sex:'女'
}
],
option:{
column:[
{
label:'姓名',
prop:'name'
}, {
label:'性别',
prop:'sex'
}
]
},
};
},
methods:{
handleRowSave(row,done,loading){
this.$message.success('1秒后关闭禁止表单')
setTimeout(()=>{
loading()
this.$message.success('3秒后关闭表单')
},1000)
setTimeout(()=>{
done()
},3000)
},
handleRowUpdate(row,index,done,loading){
this.$message.success('1秒后关闭禁止表单')
setTimeout(()=>{
loading()
this.$message.success('3秒后关闭表单')
},1000)
setTimeout(()=>{
done()
},3000)
}
}
}
</script>
# 标题字段宽度
labelWidth
为标题的宽度,默认为110
,可以配置到option
下作用于全部,也可以单独配置每一项
<avue-crud :data="data" :option="option"></avue-crud>
<script>
export default {
data() {
return {
data: [
{
name:'张三',
sex:'男'
}, {
name:'李四',
sex:'女'
}
],
option:{
labelWidth:150,
column:[
{
labelWidth:30,
label:'姓名',
prop:'name'
}, {
label:'性别',
prop:'sex'
}
]
},
}
}
}
</script>
# 验证
配置验证字段的rules
的数据对象
<avue-crud :data="data" :option="option"></avue-crud>
<script>
export default {
data() {
return {
data: [
{
name:'张三',
sex:'男'
}, {
name:'李四',
sex:'女'
}
],
option:{
column:[
{
label:'姓名',
prop:'name',
rules: [{
required: true,
message: "请输入姓名",
trigger: "blur"
}]
}, {
label:'性别',
prop:'sex',
rules: [{
required: true,
message: "请输入性别",
trigger: "blur"
}]
}
]
},
}
}
}
</script>
# 自定义验证
TIP
自定义校验 callback 必须被调用。 更多高级用法可参考 async-validator (opens new window)。
<avue-crud :data="data" v-model="obj" :option="option" @error="error"></avue-crud>
<script>
export default {
data() {
var validatePass = (rule, value, callback)=>{
if (value === '') {
callback(new Error('请输入密码'));
} else {
callback();
}
};
var validatePass2 = (rule, value, callback)=> {
if (value === '') {
callback(new Error('请再次输入密码'));
} else if (value !== this.obj.password) {
callback(new Error('两次输入密码不一致!'));
} else {
callback();
}
};
return {
obj:{},
data: [],
option:{
column:[ {
label:'密码',
prop:'password',
rules: [{ required: true,validator: validatePass, trigger: 'blur' }]
}, {
label:'确认密码',
prop:'oldpassword',
rules: [{ required: true,validator: validatePass2, trigger: 'blur' }]
} ]
}
};
},
methods: {
error(err){
this.$message.success('请查看控制台');
console.log(err)
}
}
}
</script>
# 组件对象
TIP
2.6.2+
打开表单的时候可以获取相关字段的ref对象
<avue-crud ref="crud" :data="data" :before-open="beforeOpen" :option="option"></avue-crud>
<script>
export default {
data() {
return {
data:[{
text:'测试数据'
}],
option:{
labelWidth: 120,
column: [{
label: '测试框',
prop: 'text',
}]
}
};
},
methods:{
beforeOpen(done){
done()
setTimeout(()=>{
this.$message.success('查看控制台');
console.log('text的ref对象')
console.log(this.$refs.crud.getPropRef('text'))
},0)
}
}
}
</script>
# 字段不同状态
TIP
2.6.7+
disabled
、display
、detail
等字段在新增和编辑不同状态下,字段的不同状态展示
<avue-crud :data="data" :option="option" ></avue-crud>
<script>
export default {
data() {
return {
data: [
{
name:'张三',
sex:'男',
grade:0
}, {
name:'李四',
sex:'女',
grade:1
}
],
option:{
column:[
{
label:'姓名',
prop:'name',
editDisabled:true
}, {
label:'性别',
prop:'sex',
editDisplay:false
}, {
label:'权限',
prop:'grade',
editDetail:true,
addDisabled:true
}, {
label:'测试',
prop:'test',
addDisplay:false
}
]
},
};
}
}
</script>
# 深结构绑定
TIP
2.6.11+
bing
绑定深层次的结构对象,prop
也是需要填写
<avue-crud :option="option" :data="data" v-model="form">
<div slot-scope="{}" slot="bindForm">
<el-button type="primary" size="small" @click="form.deep.deep.deep.value='改变deep.deep.deep.value值'">改变deep.deep.deep.value值</el-button>
<el-button type="primary" size="small" @click="form.test='改变test值'">改变test值</el-button>
</br></br>
{{form}}
</div>
</avue-crud>
<script>
export default{
data() {
return {
form:{},
data: [{
deep:{
deep:{
deep:{
value:'我是深结构'
}
}
}
}],
option: {
labelWidth: 120,
column: [
{
label: '深结构',
prop: 'test',
bind:'deep.deep.deep.value'
},{
label: '',
prop: 'bind',
span:24,
hide:true,
formslot:true
}
]
}
}
}
}
</script>
# 字段排序
TIP
2.6.16+
配置order
的序号可以实现表单和表格字段不同的顺序
<avue-crud :data="data" :option="option" ></avue-crud>
<script>
export default {
data() {
return {
data: [
{
name:'张三',
sex:'男'
}, {
name:'李四',
sex:'女'
}
],
option:{
column:[
{
label:'姓名',
prop:'name'
}, {
label:'性别',
prop:'sex',
order:1
}
]
},
};
},
methods: {
}
}
</script>
# 表单窗口拖拽
TIP
2.5.3+
TIP
同时已经将拖拽封装成指令,在el的原声dialog上添加v-dialogDrag即可拖拽
dialogDrag
设置为true
即可拖动表单
<avue-crud :data="data" :option="option"></avue-crud>
<script>
export default {
data() {
return {
data: [
{
name:'张三',
sex:true
}, {
name:'李四',
sex:false
}
],
option:{
dialogDrag:true,
column:[
{
label:'姓名',
prop:'name',
}, {
label:'性别',
prop:'sex'
}
]
}
}
}
}
</script>
# 改变结构配置
TIP
2.8.12+
<avue-crud :defaults.sync="defaults" v-model="form" :option="option" :data="data"></avue-crud>
<script>
export default {
data(){
return {
form:{},
defaults:{},
data:[{
text1:0
}],
option:{
column: [{
label: '内容1',
prop: 'text1',
type:'radio',
dicData:[{
label:'显示',
value:0
},{
label:'隐藏',
value:1,
}]
},{
label: '内容2',
prop: 'text2',
display:true
},{
label: '内容3',
prop: 'text3'
}]
}
}
},
watch:{
'form.text1'(val){
if(val==0){
this.defaults.text2.display=true
this.defaults.text3.label='内容3'
}else{
this.defaults.text2.display=false
this.defaults.text3.label='有没有发现我变了'
}
}
}
}
</script>
# 与其它字段交互
TIP
2.8.12+
<avue-crud :data="data" :option="option" v-model="form"></avue-crud>
<script>
export default {
data(){
return {
data:[{
text1:0
}],
form:{},
option:{
column: [{
label: '内容1',
prop: 'text1',
type:'radio',
dicData:[{
label:'显示',
value:0
},{
label:'隐藏',
value:1,
}],
control:(val,form)=>{
if(val===0){
return {
text2:{
display:true
},
text3:{
label:'内容3'
}
}
}else{
return {
text2:{
display:false
},
text3:{
label:'有没有发现我变了'
}
}
}
},
},{
label: '内容2',
prop: 'text2',
display:true
},{
label: '内容3',
prop: 'text3'
}]
}
}
}
}
</script>
# 子表单
TIP
2.1.0+
TIP
这里子子表单只能用于简单的场景,复杂的场景参考父子表更加灵活
配置dynamic
的children
字段即可,配置方法和crud
组件一致,有rowAdd
和rowDel
回调函数,与crud
组件的卡槽用法一致
<avue-crud :option="option" :data="data" v-model="form"></avue-crud>
<script>
export default {
data() {
return {
form:{},
data:[{
input1:'张三',
dynamic: [{
input: 1,
select: 1,
radio: 1,
}, {
input: 2,
select: 2,
radio: 1,
}]
}],
option:{
labelWidth: 110,
column: [{
label: '输入框',
prop: "input1",
span:12,
row: true
},
{
label: '子表单',
prop: 'dynamic',
type: 'dynamic',
span:24,
children: {
// type:'form',
align: 'center',
headerAlign: 'center',
rowAdd:(done)=>{
this.$message.success('新增回调');
done({
input:'默认值'
});
},
rowDel:(row,done)=>{
this.$message.success('删除回调'+JSON.stringify(row));
done();
},
column: [{
width: 200,
label: '输入框',
prop: "input",
formslot: true,
}, {
width: 200,
label: '选择框',
prop: "select",
type: 'select',
rules:[{
type:'number',
required:true,
message:'请选择选择框',
}],
dicData: [{
label: '测试1',
value: 1
}, {
label: '测试2',
value: 2
}]
}, {
width: 200,
label: '多选',
prop: "checkbox",
type: 'checkbox',
dicData: [{
label: '测试1',
value: 1
}, {
label: '测试2',
value: 2
}]
}, {
width: 200,
label: '开关',
prop: "switch",
type: 'switch',
dicData: [{
label: '测试1',
value: 1
}, {
label: '测试2',
value: 2
}]
}, {
width: 200,
label: '数字框',
prop: "number",
type: 'number'
}]
}
},
]
}
}
}
}
</script>
# 表单分组
TIP
<avue-crud :option="option" v-model="obj" :data="data"></avue-crud>
<script>
let baseUrl = 'https://cli.avuejs.com/api/area'
export default {
data() {
return {
obj: {
name: '11'
},
data: [{
name: '张三',
sex:15,
province: '110000',
city: '110100',
area: '110101',
checkbox: ['110000']
}],
option: {
column: [{
label: '姓名',
prop: 'name',
display:false
},
{
label: '年龄',
prop: 'sex',
display:false
}],
group: [
{
label: '用户信息',
prop: 'jbxx',
icon: 'el-icon-edit-outline',
column: [
{
label: '姓名',
prop: 'name'
},
{
label: '年龄',
prop: 'sex'
}
]
}, {
label: '退款申请',
prop: 'tksq',
icon: 'el-icon-view',
column: [
{
label: '省份',
prop: 'province',
type: 'select',
props: {
label: 'name',
value: 'code'
},
cascader: ['city'],
dicUrl: `${baseUrl}/getProvince`,
rules: [
{
required: true,
message: '请选择省份',
trigger: 'blur'
}
]
},
{
label: '城市',
prop: 'city',
type: 'select',
cascader: ['area'],
props: {
label: 'name',
value: 'code'
},
cascaderIndex: 0,
dicUrl: `${baseUrl}/getCity/{{key}}`,
rules: [
{
required: true,
message: '请选择城市',
trigger: 'blur'
}
]
},
{
label: '地区',
prop: 'area',
type: 'select',
props: {
label: 'name',
value: 'code'
},
cascaderIndex: 0,
dicUrl: `${baseUrl}/getArea/{{key}}`,
rules: [
{
required: true,
message: '请选择地区',
trigger: 'blur'
}
]
}
]
}
, {
label: '用户信息',
prop: 'yhxxs',
icon: 'el-icon-edit-outline',
column: [
{
label: '测试长度',
prop: 'len',
maxlength: 5,
}, {
labelWidth: 120,
label: '测试自定义',
prop: 'names',
formslot: true
}
]
}
]
}
}
}
}
</script>
# 自定义表单
设置列的属性formslot
为true
,在卡槽中指定列的prop
加上Form
作为卡槽的名称
<avue-crud :data="data" :option="option" v-model="user">
<template slot-scope="{type,disabled}" slot="nameForm">
<el-tag v-if="type=='add'">新增</el-tag>
<el-tag v-else-if="type=='edit'">修改</el-tag>
<el-tag v-else-if="type=='view'">查看</el-tag>
<el-tag>{{user.name?user.name:'暂时没有内容'}}</el-tag>
<el-input :disabled="disabled" v-model="user.name"></el-input>
</template>
</avue-crud>
<script>
export default {
data() {
return {
user:{},
data: [
{
name:'张三',
sex:'男'
}, {
name:'李四',
sex:'女'
}
],
option:{
column:[
{
label:'姓名',
prop:'name',
formslot:true,
rules: [{
required: true,
message: "请输入姓名",
trigger: "blur"
}]
},
{
label:'性别',
prop:'sex'
}
]
},
};
},
}
</script>
# 自定义表单错误提示
设置列的属性errorslot
为true
,在卡槽中指定列的prop
加上Error
作为卡槽的名称,
<avue-crud :data="data" :option="option" >
<template slot-scope="{error}" slot="nameError">
<p style="color:green">自定义提示{{error}}</p>
</template>
</avue-crud>
<script>
export default {
data() {
return {
user:{},
data: [
{
sex:'男'
}, {
sex:'女'
}
],
option:{
column:[
{
label:'姓名',
prop:'name',
errorslot:true,
rules: [{
required: true,
message: "请输入姓名",
trigger: "blur"
}]
},
{
label:'性别',
prop:'sex'
}
]
},
};
},
}
</script>
# 自定义表单标题
设置列的属性labelslot
为true
,在卡槽中指定列的prop
加上Label
作为卡槽的名称,
<avue-crud :data="data" :option="option">
<template slot-scope="scope" slot="nameLabel">
<span>姓名 </span>
<el-tooltip class="item" effect="dark" content="文字提示" placement="top-start">
<i class="el-icon-warning"></i>
</el-tooltip>
</template>
</avue-crud>
<script>
export default {
data() {
return {
data: [
{
name:'张三',
sex:'男'
}, {
name:'李四',
sex:'女'
}
],
option:{
column:[
{
label:'姓名',
prop:'name',
labelslot:true,
rules: [{
required: true,
message: "请输入姓名",
trigger: "blur"
}]
},
{
label:'性别',
prop:'sex'
}
]
},
};
},
}
</script>