介紹
本篇文章主要介紹基于json schema 實現 vue antd 的動態表單中的第二部分:使用。
運行結果
展示表單是 antd-vue 官方的最后一個案例:antd form
image.png
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
我的公眾號
abp愛好者