组件库文档 tmui.design
表单 Form
表单包含 输入框, 单选框, 下拉选择, 多选框 等用户输入的组件。 使用表单,您可以收集、验证和提交数据。。
🌶️ 表单 Form 示例
查看模拟效果+
示例模板
vue
<template>
<tm-app ref="app" color="grey-5">
<tm-form @submit="confirm" ref="form" v-model="show" :label-width="190">
<tm-form-item desc="你可以点击提交表单来验证" required label="身份证号码" field="nameuser.a"
:rules="[{required:true,message:'不能为空',validator:(val)=>val.length>0},{required:true,message:'请输入66',validator:(val)=>val=='66'}]">
<!-- 不要问我为什么用v-model.lazy,我很受伤。 -->
<tm-input :inputPadding="[0,0]" v-model.lazy="show.nameuser.a" :transprent="true"
:showBottomBotder="false"> </tm-input>
</tm-form-item>
<tm-form-item required label="选择日期" field="cale" :rules="[{required:true,message:'请选择日期哦'}]">
<view @click="showCal=!showCal" class="flex flex-row flex-row-center-between">
<tm-text :userInteractionEnabled="false" :label='caleStr||"请选择有效日期"'></tm-text>
<tm-icon :userInteractionEnabled="false" :font-size="24" name="tmicon-angle-right"></tm-icon>
</view>
</tm-form-item>
<tm-form-item :padding="[0,0]" requiredTitleChangeColor label="选择地区" field="city" required
:rules="[{required:true,message:'请选择地区'}]">
<view @click="testClick" class="flex flex-row flex-row-center-between">
<tm-text :userInteractionEnabled="false" :label='show.cityStr||"请选择所在地区地址"'></tm-text>
<tm-icon :userInteractionEnabled="false" :font-size="24" name="tmicon-angle-right"></tm-icon>
</view>
</tm-form-item>
<tm-form-item required label="时间选择" field="time" :rules="[{required:true,message:'请选择时间+++'}]">
<view @click="showTimePickerView=!showTimePickerView" class="flex flex-row flex-row-center-between">
<tm-text :userInteractionEnabled="false" :label='timeStr||"请选择时间"'></tm-text>
<tm-icon :userInteractionEnabled="false" :font-size="24" name="tmicon-angle-right"></tm-icon>
</view>
</tm-form-item>
<tm-form-item required label="弹出选择" field="pickerStr" :rules="[{required:true,message:'请选择水果种类'}]">
<view @click="showPicker=!showPicker" class="flex flex-row flex-row-center-between">
<tm-text :userInteractionEnabled="false" :label='show.pickerStr||"请选择水果呀"'></tm-text>
<tm-icon :userInteractionEnabled="false" :font-size="24" name="tmicon-angle-right"></tm-icon>
</view>
</tm-form-item>
<tm-form-item required label="选择水果" field="radio" :rules="[{required:true,message:'请选择水果'}]">
<tm-radio-group v-model="show.radio">
<tm-radio label="苹果" value="apple"></tm-radio>
<tm-radio label="香焦" value="bonaer"></tm-radio>
</tm-radio-group>
</tm-form-item>
<tm-form-item required label="多选水果种类" field="checkbox" :rules="[{required:true,message:'请选择'}]">
<tm-checkbox-group v-model="show.checkbox">
<tm-checkbox label="苹果" value="apple"></tm-checkbox>
<tm-checkbox label="香焦" value="bonaer"></tm-checkbox>
<tm-checkbox label="香焦" value="bonaer2"></tm-checkbox>
<tm-checkbox label="香焦" value="bonaer3"></tm-checkbox>
<tm-checkbox label="香焦" value="bonaer4"></tm-checkbox>
</tm-checkbox-group>
</tm-form-item>
<tm-form-item required label="评分" field="rate" :rules="[{required:true,message:'请选择'}]">
<tm-rate v-model="show.rate" :default-value="show.rate"></tm-rate>
</tm-form-item>
<tm-form-item required label="价格选择" field="slider"
:rules="[{required:true,message:'请选择',validator:(val)=>val.reduce((a,b)=>Math.abs(a-b))!==0}]">
<tm-slider :width="450" v-model="show.slider" :default-value="show.slider"></tm-slider>
</tm-form-item>
<tm-form-item required label="分割选择" field="segtab" :rules="[{required:true,message:'请选择'}]">
<tm-segtab :width="420" :list="[{text:'苹果'},{text:'香蕉'}]" v-model="show.segtab"
:default-value="show.segtab"></tm-segtab>
</tm-form-item>
<tm-form-item label="开关" field="switch" :rules="{required:true,message:'没有选中哦'}">
<tm-switch v-model="show.switch" :default-value="show.switch" selected='hehe'></tm-switch>
</tm-form-item>
<tm-form-item required label="上传截图" field="upload" :rules="{required:true,message:'请上传'}">
<tm-upload :rows="3" :width="420" :default-value="show.upload"
url="https://mockapi.eolink.com/tNYKNA7ac71aa90bcbe83c5815871a5b419601e96a5524d/upload"
v-model="show.upload"></tm-upload>
</tm-form-item>
<tm-form-item :border="false">
<view class=" flex flex-row">
<view class="flex-1 mr-32">
<tm-button form-type="submit" label="提交表单" block></tm-button>
</view>
<view class="flex-1">
<tm-button :shadow="0" text form-type="reset" label="重置表单" block></tm-button>
</view>
</view>
</tm-form-item>
</tm-form>
<tm-calendar v-model="show.cale" v-model:show="showCal" :default-value="show.cale"></tm-calendar>
<tm-city-picker v-model="show.city" v-model:model-str="show.cityStr" v-model:show="showCity"
:default-value="show.city"></tm-city-picker>
<tm-time-picker v-model="show.time" v-model:show="showTimePickerView"
:show-detail="{year:false,month:false,day:true,hour:true}"></tm-time-picker>
<tm-picker :columns="pickerlist" v-model:model-str="show.pickerStr" v-model:show="showPicker"
:default-value="show.pickerIndex" v-model="show.pickerIndex"></tm-picker>
</tm-app>
</template>
<script lang="ts" setup>
import {
ref,
nextTick,
getCurrentInstance,
computed
} from "vue";
import * as dayjs from "@/tmui/tool/dayjs/esm/index"
import tmApp from "@/tmui/components/tm-app/tm-app.vue";
import tmInput from "@/tmui/components/tm-input/tm-input.vue";
import tmSheet from "@/tmui/components/tm-sheet/tm-sheet.vue";
import tmRadioGroup from "@/tmui/components/tm-radio-group/tm-radio-group.vue";
import tmRadio from "@/tmui/components/tm-radio/tm-radio.vue";
import tmCheckboxGroup from "@/tmui/components/tm-checkbox-group/tm-checkbox-group.vue";
import tmCheckbox from "@/tmui/components/tm-checkbox/tm-checkbox.vue";
import tmRate from "@/tmui/components/tm-rate/tm-rate.vue";
import tmSlider from "@/tmui/components/tm-slider/tm-slider.vue";
import tmSegtab from "@/tmui/components/tm-segtab/tm-segtab.vue";
import tmSwitch from "@/tmui/components/tm-switch/tm-switch.vue";
import tmUpload from "@/tmui/components/tm-upload/tm-upload.vue";
import tmCalendar from "@/tmui/components/tm-calendar/tm-calendar.vue";
import tmCityPicker from "@/tmui/components/tm-city-picker/tm-city-picker.vue";
import tmTimePicker from "@/tmui/components/tm-time-picker/tm-time-picker.vue";
import tmPicker from "@/tmui/components/tm-picker/tm-picker.vue";
import tmImage from "@/tmui/components/tm-image/tm-image.vue";
import tmButton from "@/tmui/components/tm-button/tm-button.vue";
import tmText from "@/tmui/components/tm-text/tm-text.vue";
import tmIcon from "@/tmui/components/tm-icon/tm-icon.vue";
import tmFormItem from "@/tmui/components/tm-form-item/tm-form-item.vue";
import tmForm from "@/tmui/components/tm-form/tm-form.vue";
const app = ref < InstanceType < typeof tmApp > | null > (null)
const form = ref < InstanceType < typeof tmForm > | null > (null)
const DayJs = dayjs.default;
const showCal = ref(false)
const showCity = ref(false)
const showTimePickerView = ref(false)
const showPicker = ref(false)
const pickerStr = ref("")
const pickerlist = ref([{
text: "苹果",
id: 1,
},
{
text: "香蕉",
id: 2,
},
{
text: "李子",
id: 3,
},
{
text: "椰子",
id: 4,
},
])
const show = ref({
cale: ["2022-1-4"],
caleStr: "2022-1-4",
time: '',
radio: "", //bonaer
pickerIndex: [1],
pickerStr: "",
checkbox: [],
rate: 0,
slider: [0, 50],
segtab: "",
switch: 'hehe',
upload: [],
city: [],
cityStr: "",
nameuser: {
a: "测试"
},
testff: [],
ha: false
})
const timeStr = computed(() => !show.value.time ? "" : DayJs(show.value.time).format('DD日 HH时'))
const caleStr = computed(() => {
if (!show.value.cale || !Array.isArray(show.value.cale)) return ""
if (show.value.cale.length == 0) return "";
return DayJs(show.value.cale[0]).format('YYYY年MM月DD日')
})
const confirm = (e) => {
console.log(e)
}
const testClick = () => {
showCity.value = !showCity.value
}
</script>
🌶️ 兼容性
APP-VUE | APP-NVUE | 小程序 | WEB/H5 | VUE3/TS |
---|---|---|---|---|
✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
🌱 参数
本组件含有公共属性 公共属性
参数名 | 类型 | 默认值 | 描述 |
---|---|---|---|
modelValue | Object | true | 绑定对象值 |
margin | Array<number> | [32,24] | 外间距[x,y]x=左右,y=上下 |
padding | Array<number> | [16,0] | 内间距[x,y]x=左右,y=上下 |
layout | String | horizontal | 表单标签是竖还是横排列:vertical,horizontal。 |
labelWidth | Number | 160 | 如果为0表示自动宽度。 |
labelAlign | String | left | 标签对齐方式 |
border | Boolean | true | 显示下划线。 |
transprent | Boolean | false | 是否透明背景。 |
submit,validate校验后都将得到一致的结果参数从3.1.03开始
🌹 事件
事件名 | 参数 | 返回数据 | 描述 |
---|---|---|---|
submit | - | result | 表单提交函数 |
reset | - | - | 重置表单函数 |
validate | - | result | 执行表单检验,返回验证结果对象,内有isPass属性表示是否验证通过 |
clearValidate | - | - | 清除验证函数 |
update:modelValue | - | - | 更新表单绑定值 |
从3.1.03开始,result结构如下:
ts
{
data: {
...form的modelValue数据
},
// 所有与form-item绑定的filed字段校验的结果数组。
result:{
message:string,//校验后的提示文本
validator: boolean,//是否校验通过
}[],
isPass:boolean //是否校验通过
}
🌽 slot插槽
默认default
🥗 ref方法
方法名 | 参数 | 返回值 | 描述 |
---|---|---|---|
submit | - | - | 提交表单 |
reset | - | - | 重置表单 |
validate | - | result | 手动校验表单,返回验证结果对象,内有isPass属性表示是否验证通过 |
clearValidate | - | - | 清除校验状态 |
pushKey | item:formItem | - | - |
delKey | item:formItem | - | - |
tmFormComnameId | - | - | tmFormId |
🌱 FormItem参数
本组件含有公共属性 公共属性
参数名 | 类型 | 默认值 | 描述 |
---|---|---|---|
parentClass | String | '' | 表单的父类,可以添加自定类名,影响内部 |
align | String | '' | 这个属性主要是用来让左边标题和右边的表单等内容的对齐方式.正常情况用不到.只有在左边和右边内容高度不一致时,比如右边是多行文本或者上传组件,需要上对齐时能用到.此时可以写上flex-row-top-start |
label | String | '' | 显示名称 |
desc | String | '' | 底部表单说明文字 |
margin | Array<number> | [12,12] | 外间距[x,y]x=左右,y=上下 |
padding | <Array<number> | [0,0] | 内间距[x,y]x=左右,y=上下 |
field | String | '' | 如果在forom绑定的model为深层对象,这里的名称需要如下:比如model = {a:2,b:{c:333}},如果想绑定c,则field = "b.c" |
help | String | '' | 表单底部的单项注意说明。 |
required | Boolean | false | 是否显示必填的红色星号* |
rulesv3.0.71+ | Object | Array<rulesItem> | 检验规则,格式见下方 |
border | Boolean | null | 显示下划线。 |
showErrorv3.0.71+ | Boolean | null | 校验不通过的情况下,是否显示错误信息提示 |
requiredTitleChangeColorv3.0.81+ | Boolean | true | 校验不通过时,是否让标题跟着变化文字颜色,默认是。 |
errHeightv3.1.04+ | Number | 30 | 错误空间的高度 |
在3.0.71版本以前rules只支持Object,之后支持Array<rulesItem>。为了向下兼容,之后的版本也是支持非数据校验函数。
rules类型rulesItem 格式如下:
ts
export interface rulesItem {
validator?:Function|boolean,//检验函数。可以是Promise异步回调。
required?:boolean,//是否必填。
message?:string,//检验不合格时的文本
}
🌽 FormItem slot插槽
默认default
插槽:desc,表单底部的说明文字 插槽:error,表单底部的错误插槽,返回数据 data.message,
ts
v-slot:error = "{data}"
data.message读取错误信息
💏 文档贡献
此页文档由Sunlight贡献,如果对该框架感兴趣的可以参与我们一同进步!