vue antd 基于json schema 的动态表单实现 二
2018-11-04 本文已影响40人
诸葛_小亮
介绍
本篇文章主要介绍基于json schema 实现 vue antd 的动态表单中的第二部分:使用。
运行结果
展示表单是 antd-vue 官方的最后一个案例:antd form
image.png
代码
模板代码
<template>
<div>
<dy-form :formSchema="schema" :uiSchema="uiSchema"
@onSuccess="handleSuccess"
:submiting="submiting"
></dy-form>
</div>
</template>
使用dy-form
标签,该标签主要包括以下属性
- formSchema: form数据结构,主要是json schema对象,描述表单需要填写数据对象的结构
- uiSchema: form ui 展示结构,是一个 ui schema 对象,描述如何显示表单
- onSuccess: 表单提交成功执行的事件
- submitting: 表单提交中的状态
逻辑代码(ts)
逻辑代码中主要包括两个属性:uiSchema
和 schema
根据这两个只读属性,可以正常展示表单
<script lang="tsx">
import { Component, Prop, Vue } from 'vue-property-decorator';
import { State, Mutation, namespace } from 'vuex-class';
import DyForm from '@/components/dynamicform/DyForm.vue';
@Component({
components: {
DyForm,
},
})
export default class DynamicForm extends Vue {
private form: any = null;
private formItemLayout: any = {
labelCol: {
xs: { span: 24 },
sm: { span: 7 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 12 },
md: { span: 10 },
},
};
get formData(): any {
return {
name: '关云长',
};
}
// 动态表单 ui schema,描述表单展示
get uiSchema(): any {
return {
name: {
itemattrs: {
...this.formItemLayout,
},
widgetattrs: {
placeholder: '请填写姓名',
},
},
password: {
errors: {
minLength: '密码长度至少6位',
maxLength: '密码长度最多10位',
pattern: '密码必须是字母',
},
},
};
}
// 动态表单 json schema,描述表单填写数据的数据结构
get schema(): any {
return {
required: ['name'],
properties: {
name: {
type: 'string',
title: '姓名',
ui: {
errors: {
required: '姓名为必填项',
},
},
},
password: {
type: 'string',
title: '密码[长度|正则 验证]',
minLength: 6,
maxLength: 10,
pattern: '^[A-Za-z]+$',
ui: {
itemattrs: {
...this.formItemLayout,
},
},
},
age: {
type: 'number',
title: '年龄',
ui: {
itemattrs: {
...this.formItemLayout,
},
widgetattrs: {
min: 0,
max: 100,
},
},
},
age1: {
type: 'number',
title: '年龄1[最大最小值验证]',
maximum: 100,
minimum: 16,
ui: {
errors: {
minimum: '年龄必须满16',
maximum: '年龄必须小于100',
},
itemattrs: {
...this.formItemLayout,
},
},
},
range: {
type: 'daterange',
title: '起止日期',
ui: {
itemattrs: {
...this.formItemLayout,
},
widgetattrs: {
style: {width: '100%'},
placeholder: ['开始日期', '结束日期'],
},
},
},
remark: {
type: 'textarea',
title: '目标描述',
ui: {
itemattrs: {
...this.formItemLayout,
},
widgetattrs: {
style: {'min-height': '32px'},
placeholder: '请输入你的阶段性工作目标',
rows: 4,
},
},
},
switch: {
type: 'boolean',
ui: {
itemattrs: {
...this.formItemLayout,
},
},
},
slider: {
type: 'slider',
ui: {
itemattrs: {
...this.formItemLayout,
},
widgetattrs: {
marks: { 0: 'A', 20: 'B', 40: 'C', 60: 'D', 80: 'E', 100: 'F' },
},
},
},
rate: {
type: 'rate',
ui: {
itemattrs: {
...this.formItemLayout,
},
widgetattrs: {
allowHalf: true,
},
},
},
select: {
type: 'select',
enum: [
{ label: 'Red', value: 'red'},
{ label: 'Green', value: 'green'},
{ label: 'Blue', value: 'blue'},
],
ui: {
itemattrs: {
...this.formItemLayout,
},
widgetattrs: {
},
},
},
select2: {
type: 'select',
title: 'Select[multiple]',
enum: [
{ label: 'Red', value: 'red'},
{ label: 'Green', value: 'green'},
{ label: 'Blue', value: 'blue'},
],
ui: {
itemattrs: {
...this.formItemLayout,
},
widgetattrs: {
mode: 'multiple',
},
},
},
radio: {
type: 'radio',
title: 'radio',
enum: [
{ label: 'item 1', value: 'a'},
{ label: 'item 2', value: 'b'},
{ label: 'item 3', value: 'c'},
],
ui: {
itemattrs: {
...this.formItemLayout,
},
widgetattrs: {
},
},
},
radio2: {
type: 'radio',
title: 'radio[button]',
enum: [
{ label: 'item 1', value: 'a'},
{ label: 'item 2', value: 'b'},
{ label: 'item 3', value: 'c'},
],
ui: {
button: true,
itemattrs: {
...this.formItemLayout,
},
widgetattrs: {
},
},
},
file1: {
type: 'string',
title: '上传文件',
ui: {
widget: 'upload',
itemattrs: {
...this.formItemLayout,
},
},
},
file2: {
type: 'string',
title: '上传文件2',
ui: {
widget: 'uploaddragger',
itemattrs: {
...this.formItemLayout,
},
},
},
},
};
}
private submiting: boolean = false;
private handleSuccess(values: any) {
// tslint:disable-next-line:no-console
console.log(values);
this.submiting = true;
setTimeout(() => {
this.submiting = false;
}, 1000);
}
}
</script>
可以使用的动态组件
目前只有几种常用的动态组件,如下所示
// 日期范围
registry.register('df-daterange', DateRangeWidget);
// 数字输入框
registry.register('df-number', NumberWidget);
// 文本框
registry.register('df-string', StringWidget);
registry.register('df-text', TextWidget);
// 区域文本框
registry.register('df-textarea', TextareaWidget);
// 开关
registry.register('df-boolean', SwitchWidget);
// 拖动条
registry.register('df-slider', SliderWidget);
// 星打分
registry.register('df-rate', RateWidget);
// 下拉框
registry.register('df-select', SelectWidget);
// 单选框
registry.register('df-radio', RadioWidget);
// 上传文件
registry.register('df-upload', UploadWidget);
registry.register('df-uploaddragger', UploadDraggerWidget);
如果我们将ui shcmea 中的 widget 的type指定为 df-radio,则表示使用单选框渲染组件
参考资料
ng-alain-form
json shcema
antd-vue