小程序封装表单组件,含校验功能

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)
        })
    },```

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值