# t-form-dynamic
FormDynamic 动态表单
t-form-dynamic 组件介绍
动态表单组件,根据JSON配置生成表单,支持多种表单字段类型和校验规则,适用于需要根据后端配置生成表单的场景。
t-form-dynamic 平台兼容
| Harmony | H5 | Android | iOS | 小程序 | UTS |
|---|---|---|---|---|---|
| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
t-form-dynamic 基础用法
vue
<template>
<view :class="[`p-15 tpg`]">
<tui-theme-switch></tui-theme-switch>
<t-card class="mb-15"
title="DynamicForm 动态表单"
sub-title="后端配置json,前端动态展示表单填写,适用于政务办件后台制作表格的展示"></t-card>
<t-form-dynamic ref="ruleForm"
v-if="list.length>0"
:options="childs"
:forms="formdata"
:rules="rules"
:disabled="disabled"
class="r-10 oh mb-15 plr-10"
child-class="ptb-10"></t-form-dynamic>
<t-button class="mb-15"
type="primary"
@click="submitForm">提交</t-button>
<t-button class="mb-15"
type="success"
@click="resetForm">重置</t-button>
<t-button type="error"
@click="disabled=!disabled">{{disabled?'取消禁用':'禁用表单'}}</t-button>
</view>
</template>
<script setup>
import { isPhone } from '@/uni_modules/tui-common'
import { TuiApi } from '@/api'
const disabled = ref(false)
const ruleForm = ref<ComponentPublicInstance | null>(null)
const list = ref<UTSJSONObject[]>([])
// @tui-autocss-include
const sty : string = 'f sta-r p-10 fl fww fjce p-0 ml-10 ml-8 h-80 mb-15 s-30! b bgn'
// sty是告诉编译器JSON配置中用到了哪些元子化样式如果class样式已经写在style中了,则可以不写以上代码
const childs = ref<UTSJSONObject[]>([
{
type: "pickerSelect",
label: '下拉选择',
name: 'pickerselectvalue',
attrs: {
class: 'f',
list: [{
value: '选项1',
label: '黄金糕'
}, {
value: '选项2',
label: '双皮奶',
disabled: true
}, {
value: '选项3',
label: '蚵仔煎'
}, {
value: '选项4',
label: '龙须面'
}, {
value: '选项5',
label: '北京烤鸭'
}]
}
},
{
label: '手机号',
type: 'input',
name: 'phone',
itemAttrs: {},
attrs: {
'placeholder-class': 'sta-r',
'input-class': 'sta-r',
class: 'f p-10 bgn',
mode: 'number',
maxlength: 11,
placeholder: "请输入手机号"
}
}, {
label: '性别 ',
type: 'radio',
name: 'gender',
itemAttrs: {},
attrs: { type: 'primary', class: "f fl fww fjce", 'child-class': "p-0 ml-10" },
list: [
{
value: '1',
label: '男'
},
{
value: '2',
label: '女'
}, {
value: '3',
label: '保密'
}
]
}, {
label: '爱好 ',
type: 'checkbox',
name: 'hobby',
itemAttrs: {},
attrs: {
class: "`f fl fww fjce`",
type: "primary",
childClass: "p-0 ml-8",
transition: false
},
list: [
{
value: '1',
label: '学习'
},
{
value: '2',
label: '泡妞'
}, {
value: '3',
label: '看书'
}
]
},
{
label: "验证码",
name: "codeinput",
type: "code",
itemAttrs: {},
attrs: {
type: "primary",
dotSymbol: "",
maxlength: 4
}
},
{
label: "评分",
name: "ratecount",
type: "rate",
itemAttrs: {},
attrs: {
'icon-class': "s-30!",
type: "primary"
}
},
{
label: "开关",
name: "switchs",
type: "switch",
itemAttrs: {},
attrs: {
type: "primary",
activeIcon: 'volume-up',
inactiveIcon: 'volume-off'
}
},
{
label: "上传",
name: "uploads",
type: "upload",
itemAttrs: {},
attrs: {
count: 1
}
},
{
label: "步进器",
name: "numberbox",
type: "stepper",
itemAttrs: {},
attrs: { min: 3, max: 99, type: "success" }
},
{
label: "滑块",
name: "sliderval",
type: "slider",
itemAttrs: {},
attrs: {
class: 'f h-80 mb-15 ', direction: 'horizontal', min: 0, max: 500, blockSize: '30', disabled: false, showValue: true, trackSize: '10', showMode: 'after'
}
},
{
label: '文本',
type: 'textarea',
name: 'textareavalue',
itemAttrs: {
bottomLine: false, direction: "col"
},
attrs: {
effect: "plain",
placeholder: "欢迎使用Tui",
class: "tui-border-test",
onInput: (e : UniInputEvent) => {
uni.showToast({
title: e.detail.value
})
}
}
},
{
label: "颜色设置",
name: "colorvalue",
type: "color",
itemAttrs: {
bottomLine: false
}
},
{
label: "时间选择",
type: 'date',
name: "datevalue",
itemAttrs: {},
attrs: {
class: "f",
format: "yyyy-mm-dd",
range: [
{
type: 'year',
name: '年',
start: 1900,
end: 2999
},
{
type: 'month',
name: '月',
start: 1,
end: 12
},
{
type: 'date',
name: '日',
start: 1,
end: 31
}
]
}
}, {
label: "弹窗日历测试",
type: 'pickercalendar',
name: "pickercalendar",
itemAttrs: {},
attrs: {
vertical: false,
mode: "single",
class: "f",
selected: [{
date: '2025-3-17',
info: '打折',
infoColor: '#00cc81',
badge: true,
badgeInfo: '休',
badgeColor: '#ff0000',
disabled: true
}]
}
}, {
label: "级联表单",
type: 'cascader',
name: "cascader",
itemAttrs: {
direction: "col", showLabel: false
},
attrs: {
type: "p",
option: [
{
"value": "zhinan",
"label": "指南",
"children": [
{
"value": "shejiyuanze",
"label": "设计原则",
"children": [
{
"value": "yizhi",
"label": "一致",
"disabled": true
},
{
"value": "fankui",
"label": "反馈"
},
{
"value": "xiaolv",
"label": "效率"
},
{
"value": "kekong",
"label": "可控"
}
]
},
{
"value": "daohang",
"label": "导航",
"children": [
{
"value": "cexiangdaohang",
"label": "侧向导航"
},
{
"value": "dingbudaohang",
"label": "顶部导航"
}
]
}
]
},
{
"value": "zujian",
"label": "组件",
"children": [
{
"value": "basic",
"label": "Basic",
"children": [
{
"value": "layout",
"label": "Layout 布局"
},
{
"value": "color",
"label": "Color 色彩"
},
{
"value": "typography",
"label": "Typography 字体"
},
{
"value": "icon",
"label": "Icon 图标"
},
{
"value": "button",
"label": "Button 按钮"
}
]
},
{
"value": "form",
"label": "Form",
"children": [
{
"value": "radio",
"label": "Radio 单选框"
},
{
"value": "checkbox",
"label": "Checkbox 多选框"
},
{
"value": "input",
"label": "Input 输入框"
},
{
"value": "input-number",
"label": "InputNumber 计数器"
},
{
"value": "select",
"label": "Select 选择器"
},
{
"value": "cascader",
"label": "Cascader 级联选择器"
},
{
"value": "switch",
"label": "Switch 开关"
},
{
"value": "slider",
"label": "Slider 滑块"
},
{
"value": "time-picker",
"label": "TimePicker 时间选择器"
},
{
"value": "date-picker",
"label": "DatePicker 日期选择器"
},
{
"value": "datetime-picker",
"label": "DateTimePicker 日期时间选择器"
},
{
"value": "upload",
"label": "Upload 上传"
},
{
"value": "rate",
"label": "Rate 评分"
},
{
"value": "form",
"label": "Form 表单"
}
]
},
{
"value": "data",
"label": "Data",
"children": [
{
"value": "table",
"label": "Table 表格"
},
{
"value": "tag",
"label": "Tag 标签"
},
{
"value": "progress",
"label": "Progress 进度条"
},
{
"value": "tree",
"label": "Tree 树形控件"
},
{
"value": "pagination",
"label": "Pagination 分页"
},
{
"value": "badge",
"label": "Badge 标记"
}
]
},
{
"value": "notice",
"label": "Notice",
"children": [
{
"value": "alert",
"label": "Alert 警告"
},
{
"value": "loading",
"label": "Loading 加载"
},
{
"value": "message",
"label": "Message 消息提示"
},
{
"value": "message-box",
"label": "MessageBox 弹框"
},
{
"value": "notification",
"label": "Notification 通知"
}
]
},
{
"value": "navigation",
"label": "Navigation",
"children": [
{
"value": "menu",
"label": "NavMenu 导航菜单"
},
{
"value": "tabs",
"label": "Tabs 标签页"
},
{
"value": "breadcrumb",
"label": "Breadcrumb 面包屑"
},
{
"value": "dropdown",
"label": "Dropdown 下拉菜单"
},
{
"value": "steps",
"label": "Steps 步骤条"
}
]
},
{
"value": "others",
"label": "Others",
"children": [
{
"value": "dialog",
"label": "Dialog 对话框"
},
{
"value": "tooltip",
"label": "Tooltip 文字提示"
},
{
"value": "popover",
"label": "Popover 弹出框"
},
{
"value": "card",
"label": "Card 卡片"
},
{
"value": "carousel",
"label": "Carousel 走马灯"
},
{
"value": "collapse",
"label": "Collapse 折叠面板"
}
]
}
]
},
{
"value": "ziyuan",
"label": "资源",
"children": [
{
"value": "axure",
"label": "Axure Components"
},
{
"value": "sketch",
"label": "Sketch Templates"
},
{
"value": "jiaohu",
"label": "组件交互文档"
}
]
}
]
}
}, {
label: "文件选择",
type: 'filemanager',
name: "filemanager",
itemAttrs: { direction: "col", showLabel: false },
attrs: { type: 'primary' }
}
])
const formdata = ref<UTSJSONObject>({
phone: '15329438335',
gender: '2',
hobby: ['1', '3'],
codeinput: '1',
ratecount: 3,
switchs: true,
uploads: [{ path: '/static/image/6527ae979850d.jpg' }],
numberbox: 15,
sliderval: [0, 105, 500],
textareavalue: '文本域内容',
colorvalue: '#2979ff',
datevalue: '',
school: [] as string[],
cityvalue: [] as string[],
calendar: ['2025-3-18', '2025-3-28'],
pickercalendar: [] as string[],
cascader: [] as string[],
filemanager: [] as UTSJSONObject[],
pickerselectvalue: ''
})
const rules = ref<UTSJSONObject>({
phone: [
{ type: 'required', message: '手机号不能为空' },
{ type: 'length', min: 11, max: 11, message: '手机号长度只能为11位' },
{
type: 'function',
fun: (e : any) : boolean => {
return isPhone(`${e}`)
},
message: '手机号正则验证失败'
}
]
})
function submitForm() {
const validate : boolean = (ruleForm.value!).$callMethod('validate') as boolean
if (validate) {
uni.showModal({
title: '数据提交成功'
})
disabled.value = !disabled.value
} else {
uni.showModal({
title: '数据校验失败'
})
}
}
function resetForm() {
(ruleForm.value!).$callMethod('reset')
}
onLoad((_) => {
TuiApi('citydata', {}, false).then((res : UTSJSONObject) => {
let arr = res.getArray('data') as UTSJSONObject[]
childs.value.push({
label: "地区选择",
type: 'city',
name: 'cityvalue',
itemAttrs: {},
attrs: {
class: "f",
list: arr
}
})
list.value = arr
})
})
</script>
<style>
.tui-border-test {
border: 1px solid #e5e5e5;
flex: 1;
}
</style>t-form-dynamic Props
| 属性名 | 类型 | 默认值 | 说明 | 可选值 |
|---|---|---|---|---|
| size | String | "" | 组件尺寸 | large, medium, small, mini |
| type | String | "" | 组件类型 | info, primary, error, warning, success |
| disabled | Boolean | false | 组件是否禁用 | true, false |
| hover | Boolean | false | 是否有点击效果 | true, false |
| path | String | "" | 点击组件后跳转的页面路径 | - |
| effect | String | "" | 组件显示主题 | normal, dark, light, plain |
| options | Array | [] | 动态表单的配置 | - |
| forms | Object | {} | 绑定表单的值 | - |
| rules | Object | {} | 校验规则配置 | - |
| showLabel | Boolean | true | 是否显示header | true, false |
| direction | String | "row" | 表单的布局的方向 | row, column |
| rulesClass | String | "" | 规则样式 | - |
| labelClass | String | "" | 标签样式 | - |
| childClass | String | "" | 统一设置子组件样式 | - |
| requiredAsterisk | String | "*" | 必填时的提示符 | - |
| requiredAsteriskClass | String | "mt-10" | 必填提示符的样式 | - |
| hideRequiredAsterisk | Boolean | false | 隐藏必填提示符 | true, false |
| showMessage | Boolean | true | 是否显示验证信息 | true, false |
| bottomLine | Boolean | false | 是否显示底部线条 | true, false |
t-form-dynamic Events
| 事件名 | 说明 | 回调参数 |
|---|---|---|
| click | 点击时触发 | - |
| touchstart | 触摸开始时触发 | 触摸事件对象 |
| touchend | 触摸结束时触发 | 触摸事件对象 |
| touchmove | 触摸移动时触发 | 触摸事件对象 |
| touchcancel | 触摸取消时触发 | 触摸事件对象 |
Methods
| 方法名 | 说明 | 参数 | 返回值 |
|---|---|---|---|
| validate | 验证表单 | 无 | Boolean |
| reset | 重置表单 | 无 | 无 |
t-form-dynamic Slots
| 插槽名 | 说明 |
|---|---|
| default | 自定义表单字段内容,接收item和index参数 |