input
form-item组件
<view class="label"><text wx:if="{{ required }}" class="asterisk">*</text>{{ ch }}</view>
<van-field wx:if="{{ !isPassword }}" model:value="{{ form[param] }}" key='field' hold-keyboard="{{ true }}"
placeholder="请输入{{ ch }}" error-message="{{ error }}" border="{{ border }}" readonly="{{ readonly }}"
type="{{ type }}" data-param="{{ param }}"
class="{{ type === 'textarea' ? 'desc-input' : '' }} {{ readonly ? 'readonly-field' : '' }}" bind:change="onChange" />
<van-field wx:else model:value="{{ form[param] }}" key='field' hold-keyboard="{{ true }}" placeholder="请输入{{ ch }}"
error-message="{{ error }}" border="{{ border }}" readonly="{{ readonly }}" password="{{ showPassword }}"
data-param="{{ param }}"
class="{{ type === 'textarea' ? 'desc-input' : '' }} {{ readonly ? 'readonly-field' : '' }}" bind:change="onChange">
<van-icon class="icon-eye" wx:if="{{ isPassword }}" slot="button" name="{{showPassword?'eye-o':'closed-eye'}}" bind:touchstart="handleEyeTouchstart" bind:touchend="handleEyeTouchend" bind:touchcancel="handleEyeTouchend" />
<!-- <van-icon wx:if="{{ isPassword && !showPassword }}" slot="button" name="closed-eye" bind:touchstart="handleEyeShow" /> -->
</van-field>
// components/form-item/form-item.js
Component({
options: {
multipleSlots: true // 在组件定义时的选项中启用多slot支持
},
/**
* 组件的属性列表
*/
properties: {
form: {
type: Object,
value: {}
},
required: {
type: Boolean,
value: false
},
param: {
// 字段名称
type: String,
value: ''
},
ch: {
type: String,
value: ''
},
border: {
type: Boolean,
value: true
},
readonly: {
type: Boolean,
value: false
},
type: {
type: String,
value: 'text'
},
isPassword: {
type: Boolean,
value: false
}
},
/**
* 组件的初始数据
*/
data: {
error: '',
showPassword: true
},
/**
* 组件的方法列表
*/
methods: {
handleEyeTouchstart() {
this.setData({
showPassword: false,
})
},
handleEyeTouchend(){
this.setData({
showPassword: true,
})
},
showError() {
this.setData({
error: `请输入${this.data.ch}`
})
},
hideError() {
this.setData({
error: ""
})
},
onChange(event) {
const {
param
} = event.currentTarget.dataset
if (event.detail) {
this.setData({
error: ''
})
} else {
this.setData({
error: `请输入${this.data.ch}`
})
}
const form = this.data.form
form[param] = event.detail
this.setData({
form
})
// 传给父
this.triggerEvent('changeForm', form)
},
}
})
日期选择
date-form-item
<view wx:if="{{ !row }}" class="label"><text wx:if="{{ required }}" class="asterisk">*</text>{{ ch }}</view>
<van-field label="{{ row ? ch : '' }}" value="{{ form[param] }}" placeholder="请选择{{ ch }}" error-message="{{ error }}"
border="{{ true }}" readonly bind:click-input="clickInput">
<van-icon slot="right-icon" name="arrow-down"
style="transition: all 0.3s; transform: {{ rotate ? 'rotate(0deg)' : 'rotate(180deg)' }};" />
</van-field>
<van-popup show="{{ showPopup }}" round position="bottom" bind:close="onClosePopup">
<van-datetime-picker type="date" data-type="end" value="{{ currentDate }}" data-param="{{ param }}" min-date="{{ minDate }}" formatter="{{ formatter }}"
bind:cancel="cancelDate" bind:confirm="onConfirmPopup" />
</van-popup>
// components/drop-down-form-item/drop-down-form-item.js
const app = getApp()
const { themeColor } = app.globalData
// Utils
import {
parseTime
} from "../../utils/utils"
Component({
/**
* 组件的属性列表
*/
properties: {
form: {
type: Object,
value: {}
},
required: {
// 非必须
type: Boolean,
value: false
},
param: {
// 字段名称
type: String,
value: ''
},
ch: {
// 中文
type: String,
value: ''
},
list: {
type: Array,
value: []
},
// 单行展示
row: {
type: Boolean,
value: false
},
minDate: {
type: String,
value: new Date().getTime()
}
},
/**
* 组件的初始数据
*/
data: {
themeColor,
rotate: true,
showPopup: false,
error: '',
currentDate: null,
formatter(type, value) {
if (type === 'year') {
return `${value}年`;
}
if (type === 'month') {
return `${value}月`;
}
return value;
},
},
/**
* 组件的方法列表
*/
methods: {
showError () {
this.setData({
error: `请输入${this.data.ch}`
})
},
hideError() {
this.setData({
error: ""
})
},
clickInput() {
this.setData({
rotate: !this.data.rotate,
showPopup: !this.data.showPopup
})
},
cancelDate() {
this.setData({
showPopup: false,
rotate: true
})
},
onConfirmPopup(event) {
const {
param
} = event.currentTarget.dataset
if (event.detail) {
this.setData({
error: ''
})
} else {
this.setData({
error: `请选择${this.data.ch}`
})
}
const form = this.data.form
// TODO
form[param] = parseTime(event.detail, '{y}-{m}-{d}')
this.setData({
showPopup: false,
rotate: true
})
// 传给父
this.triggerEvent('changeForm', form)
},
onClosePopup() {
this.setData({
showPopup: false,
rotate: true
})
},
},
ready() {
this.setData({
currentDate: new Date(this.data.form[this.data.param]).getTime()
})
}
})
下拉选择/picker
drop-down-form-item
<view wx:if="{{ !row }}" class="label"><text wx:if="{{ required }}" class="asterisk">*</text>{{ ch }}</view>
<van-field label="{{ row ? ch : '' }}" value="{{ form[param].label }}" placeholder="请选择{{ ch }}" error-message="{{ error }}" border="{{ border }}"
readonly bind:click-input="clickInput">
<van-icon slot="right-icon" name="arrow-down"
style="transition: all 0.3s; transform: {{ rotate ? 'rotate(0deg)' : 'rotate(180deg)' }};" />
</van-field>
<van-popup show="{{ showPopup }}" round position="bottom" bind:close="onClosePopup">
<van-picker title="选择{{ ch }}" default-index="{{ defaultIndex }}" columns="{{ list }}" value-key="label" data-param="{{ param }}" show-toolbar
bind:cancel="onClosePopup" bind:confirm="onConfirmPopup" />
</van-popup>
// components/drop-down-form-item/drop-down-form-item.js
Component({
/**
* 组件的属性列表
*/
properties: {
form: {
type: Object,
value: {}
},
required: {
// 非必须
type: Boolean,
value: false
},
param: {
// 字段名称
type: String,
value: ''
},
ch: {
// 中文
type: String,
value: ''
},
list: {
type: Array,
value: []
},
// 单行展示
row: {
type: Boolean,
value: false
},
border: {
type: Boolean,
value: true
},
readonly: {
type: Boolean,
value: false
},
},
/**
* 组件的初始数据
*/
data: {
rotate: true,
showPopup: false,
error: '',
defaultIndex: 0
},
/**
* 组件的方法列表
*/
methods: {
showError() {
this.setData({
error: `请输入${this.data.ch}`
})
},
hideError() {
this.setData({
error: ""
})
},
clickInput() {
if (this.data.readonly) {
return
}
this.setData({
rotate: !this.data.rotate,
showPopup: !this.data.showPopup
})
},
onConfirmPopup(event) {
const {
param
} = event.currentTarget.dataset
if (event.detail.value) {
this.setData({
error: ''
})
} else {
this.setData({
error: `请输入${this.data.ch}`
})
}
const form = this.data.form
const {
label,
value
} = event.detail.value
// TODO
form[param] = {
label,
value
}
this.setData({
showPopup: false,
rotate: true
})
// 传给父
this.triggerEvent('changeForm', form)
},
onClosePopup() {
this.setData({
showPopup: false,
rotate: true
})
},
},
ready() {
const {
value
} = this.data.form[this.data.param]
if (value) {
const defaultIndex = this.data.list.findIndex(ele => ele.value === value)
this.setData({
defaultIndex
})
}
}
})
父组件
<form-item id="empname" form="{{ form }}" required="{{ false }}" param="empname" ch="用户名"
class="form-item" readonly="{{ true }}" bind:changeForm="changeForm" />
<form-item id="empcode" form="{{ form }}" required="{{ false }}" readonly="{{ true }}" param="empcode" ch="工号" class="form-item"
bind:changeForm="changeForm" />
<drop-down-form-item id="canteen" form="{{ form }}" required="{{ true }}" param="canteen"
ch="默认报餐餐厅" list="{{ canteenList }}" bind:changeForm="changeForm"></drop-down-form-item>
<form-item id="tel" form="{{ form }}" required="{{ true }}" param="tel" ch="手机号码"
bind:changeForm="changeForm" />
<form-item id="password_bf" form="{{ form }}" required="{{ true }}" border="{{ false }}" type="password" is-password="{{ true }}"
param="password_bf" ch="登录密码" bind:changeForm="changeForm" />
changeForm(form) {
this.setData({
form: Object.assign({}, this.data.form, form.detail)
})
},```