TaleLin / lin-ui

🌈 简洁、易用、灵活的微信小程序组件库
https://doc.mini.talelin.com
MIT License
4.08k stars 484 forks source link

关于Picker组件引入form检测案例 #1496

Open CHEN-J-H opened 2 years ago

CHEN-J-H commented 2 years ago

Feature 名称: picker组件使用案例

简要描述: 引入picker方便form检测

使用场景: 表单组件模块

其他组件库或类似功能的截图:

image
CHEN-J-H commented 2 years ago

src目录下新建picker

index.js

import eventBus from '../core/utils/event-bus';

Component({
  externalClasses: ['l-class'],
  properties: {
    arr: {
      type: Array
    },
    currentIndex: {
      type: null,
      optionalTypes: [String, Number],
      value: ''
    },
    showIcon: {
      type: Boolean
    },
    rangeKey: {
      type: String,
      value: 'label'
    },
    placeholder: {
      type: String,
      value: '请选择相关选项'
    }
  },

  methods: {
    handleFormChange(event) {
      this.setData({
        currentIndex: event.detail.value
      });
      eventBus.emit(`lin-form-change-${this.id}`, this.id);
      this.triggerEvent('linchange', event.detail);
    },

    getValues() {
      return this.data.currentIndex;
    },

    reset() {
      this.setData({
        currentIndex: ''
      });
    }
  }
});

index.json

{
    "component": true,
    "usingComponents": {
        "l-icon": "../icon/index"
    }
}

index.wxml

<view class="picker l-class">
  <picker range='{{arr}}' value="{{currentIndex}}" range-key='{{rangeKey}}' bindchange="handleFormChange">
    <view class="pickerText">
      <view style="color:{{arr[currentIndex][rangeKey] ?'#333':'#8f8f8f'}}">
        {{ arr[currentIndex][rangeKey] ? arr[currentIndex][rangeKey] : placeholder }}
      </view>
      <!-- <view class="icon iconfont icon-right-outlined" style="color:{{form.industry?'#333':'#8f8f8f'}}"> -->
      <!-- </view> -->
      <l-icon wx:if="{{showIcon}}" name="right" color="#333" size="28" />
    </view>
  </picker>
</view>

index.less

.picker {
  box-sizing: border-box;
  display: flex;
  flex-direction: row;
  align-items: center;
  padding-left: 25rpx;
  height: 88rpx;
  padding-right: 25rpx;

  picker {
    width: 100%;

    .pickerText {
      font-size: 28rpx;
      flex: 1;
      display: flex;
      justify-content: space-between;
      align-items: center;
    }
  }

}

使用方法


            <l-form-item label="密码:" name="loginFormPicker" rules="{{loginForm.PickerRules}}">
                        <l-picker arr="{{job}}" id="loginFormPicker"/>
                    </l-form-item>

PickerRules的规则是


   PickerRules: [{
        required: true,
        message: '22221',
        trigger: 'change'
      }],

经过测试后是有效的,picker纳入监测机制,提交收到所有form值

此组件仅针对我个人业务需求,大家可以举一反三

CHEN-J-H commented 2 years ago

关键带码就是methods里面的三个方法。最关键的就是 eventBus.emit(lin-form-change-${this.id}, this.id); 这一句代码

CHEN-J-H commented 2 years ago

业务需求 所有验证通过之后 提交按钮才能提交 修改了一下Form组件的代码

import eventBus from '../core/utils/event-bus.js';
import eventUtil from '../core/utils/event-util';
Component({
  /**
     * 组件的属性列表
     */
  externalClasses: ['l-form-container-class', 'l-form-submit-class', 'l-form-reset-class', 'l-form-btn-class'],
  options: {
    multipleSlots: true,
  },
  relations: {
    '../form-item/index': {
      type: 'child',
      linked: function (target) {
        this._initItem(target);
      },
      linkChanged: function () {
      },
      unlinked: function () {
      }
    }
  },

  properties: {
    name: {
      type: String,
      value: ''
    },
    isSubmitValidate: {
      type: Boolean,
      value: true
    }
  },

  attached() {
    this._init();
  },
  detached() {
    for (let key in this._keys) {
      if (Object.prototype.hasOwnProperty.call(this._keys, key)) {
        eventBus.off(`lin-form-blur-${key}`);
        eventBus.off(`lin-form-change-${key}`);
      }
    }
  },

  /**
     * 组件的初始数据
     */
  data: {
    _this: null
  },

  /**
     * 组件的方法列表
     */
  methods: {
    _init() {
      wx.lin = wx.lin || {};
      wx.lin.forms = wx.lin.forms || {};
      wx.lin.forms[this.properties.name] = this;
      wx.lin.initValidateForm = (_this) => {
        wx.lin._instantiation = _this;
      };
      wx.lin.validateForm = function (name, callback) {
        wx.lin.forms[name]._validateForm(callback);
      };
      wx.lin.submitForm = function (name) {
        wx.lin.forms[name].submit();
      };
      wx.lin.resetForm = function (name) {
        wx.lin.forms[name].reset();
      };

    },

    _initItem(target) {
      this._keys = this._keys || {};
      this._errors = this._errors || {};
      const key = target.properties.name;
      eventBus.on(`lin-form-blur-${key}`, (id) => {
        this._validateItem(id, 'blur');
        // clearTimeout(this.blur_time)
        // this.blur_time = setTimeout(()=>{
        //   this._validateItem(id, 'blur');
        // }, 200)
      });
      eventBus.on(`lin-form-change-${key}`, (id) => {
        clearTimeout(this.change_time);
        this.change_time = setTimeout(() => {
          this._validateItem(id, 'change');
        }, 200);
      });
      if (this._keys[key]) {
        throw new Error(`表单项存在重复的name:${key}`);
      }
      this._keys[key] = '';
      this._errors[key] = [];
    },

    _validateItem(id, type) {
      let _this = wx.lin._instantiation;

      let params = this._getValues();

      const items = this.getRelationNodes('../form-item/index');
      const currentTarget = items.find(item => item.properties.name === id);
      const formItem = _this.selectComponent(`#${id}`);
      if (formItem) {
        currentTarget.validatorData(params, type);
      } else {
        throw new Error(`表单项不存在name:${id}`);
      }
      this._errors[id] = currentTarget.data.errors;
      return currentTarget.data.errors;
    },

    _forEachNodes(func, isReverse) {
      let items = this.getRelationNodes('../form-item/index');
      if (isReverse) {
        items.reverse();
      }
      items.forEach((item, index) => {
        func(item, index);
      });
    },

    _validateForm(callback) {
      let _this = wx.lin._instantiation;
      // 校验name的rule
      let formErrors = [];
      let params = this._getValues();
      this._forEachNodes(item => {
        const id = item.properties.name;
        const formItem = _this.selectComponent(`#${id}`);
        if (formItem) {
          item.validatorData(params);
        } else {
          throw new Error(`表单项不存在name:${id}`);
        }
        this._errors[id] = item.data.errors;
        formErrors = formErrors.concat(item.data.errors);
      }, true);
      callback && callback(formErrors);
      return formErrors;
    },

    _getValues() {
      let params = {};
      let _this = wx.lin._instantiation;

      this._forEachNodes(item => {
        const _id = item.properties.name;
        const formItem = _this.selectComponent(`#${_id}`);
        if (formItem) {
          params[_id] = formItem.getValues();
        }
      });
      return params;
    },

    submit() {
      let errors = this.data.isSubmitValidate ? this._validateForm() : [];
      this.triggerEvent('linsubmit', {
        values: this._getValues(),
        errors: this.data.isSubmitValidate ? this._errors : {},
        isValidate: errors.length === 0
      });
    },
    reset() {
      let _this = wx.lin._instantiation;
      this._forEachNodes((item) => {
        item.setData({
          errorText: ''
        });
        const _id = item.properties.name;
        const formItem = _this.selectComponent(`#${_id}`);
        if (formItem) {
          formItem.reset();
        }
      });
      eventUtil.emit(this, 'linreset');
    }
  }
});

关键代码

  wx.lin.validateForm = function (name, callback) {
        wx.lin.forms[name]._validateForm(callback);
      };

_validateForm(callback) {
      let _this = wx.lin._instantiation;
      // 校验name的rule
      let formErrors = [];
      let params = this._getValues();
      this._forEachNodes(item => {
        const id = item.properties.name;
        const formItem = _this.selectComponent(`#${id}`);
        if (formItem) {
          item.validatorData(params);
        } else {
          throw new Error(`表单项不存在name:${id}`);
        }
        this._errors[id] = item.data.errors;
        formErrors = formErrors.concat(item.data.errors);
      }, true);
      callback && callback(formErrors);
      return formErrors;
    },

使用方法


   wx.lin.validateForm('FormName',(errs)=>{
      console.log(errs)
    });

随时可以检测当前还有多少个错误

CHEN-J-H commented 2 years ago

业务需求 所有验证通过之后 提交按钮才能提交 修改了一下Form组件的代码

import eventBus from '../core/utils/event-bus.js';
import eventUtil from '../core/utils/event-util';
Component({
  /**
     * 组件的属性列表
     */
  externalClasses: ['l-form-container-class', 'l-form-submit-class', 'l-form-reset-class', 'l-form-btn-class'],
  options: {
    multipleSlots: true,
  },
  relations: {
    '../form-item/index': {
      type: 'child',
      linked: function (target) {
        this._initItem(target);
      },
      linkChanged: function () {
      },
      unlinked: function () {
      }
    }
  },

  properties: {
    name: {
      type: String,
      value: ''
    },
    isSubmitValidate: {
      type: Boolean,
      value: true
    }
  },

  attached() {
    this._init();
  },
  detached() {
    for (let key in this._keys) {
      if (Object.prototype.hasOwnProperty.call(this._keys, key)) {
        eventBus.off(`lin-form-blur-${key}`);
        eventBus.off(`lin-form-change-${key}`);
      }
    }
  },

  /**
     * 组件的初始数据
     */
  data: {
    _this: null
  },

  /**
     * 组件的方法列表
     */
  methods: {
    _init() {
      wx.lin = wx.lin || {};
      wx.lin.forms = wx.lin.forms || {};
      wx.lin.forms[this.properties.name] = this;
      wx.lin.initValidateForm = (_this) => {
        wx.lin._instantiation = _this;
      };
      wx.lin.validateForm = function (name, callback) {
        wx.lin.forms[name]._validateForm(callback);
      };
      wx.lin.submitForm = function (name) {
        wx.lin.forms[name].submit();
      };
      wx.lin.resetForm = function (name) {
        wx.lin.forms[name].reset();
      };

    },

    _initItem(target) {
      this._keys = this._keys || {};
      this._errors = this._errors || {};
      const key = target.properties.name;
      eventBus.on(`lin-form-blur-${key}`, (id) => {
        this._validateItem(id, 'blur');
        // clearTimeout(this.blur_time)
        // this.blur_time = setTimeout(()=>{
        //   this._validateItem(id, 'blur');
        // }, 200)
      });
      eventBus.on(`lin-form-change-${key}`, (id) => {
        clearTimeout(this.change_time);
        this.change_time = setTimeout(() => {
          this._validateItem(id, 'change');
        }, 200);
      });
      if (this._keys[key]) {
        throw new Error(`表单项存在重复的name:${key}`);
      }
      this._keys[key] = '';
      this._errors[key] = [];
    },

    _validateItem(id, type) {
      let _this = wx.lin._instantiation;

      let params = this._getValues();

      const items = this.getRelationNodes('../form-item/index');
      const currentTarget = items.find(item => item.properties.name === id);
      const formItem = _this.selectComponent(`#${id}`);
      if (formItem) {
        currentTarget.validatorData(params, type);
      } else {
        throw new Error(`表单项不存在name:${id}`);
      }
      this._errors[id] = currentTarget.data.errors;
      return currentTarget.data.errors;
    },

    _forEachNodes(func, isReverse) {
      let items = this.getRelationNodes('../form-item/index');
      if (isReverse) {
        items.reverse();
      }
      items.forEach((item, index) => {
        func(item, index);
      });
    },

    _validateForm(callback) {
      let _this = wx.lin._instantiation;
      // 校验name的rule
      let formErrors = [];
      let params = this._getValues();
      this._forEachNodes(item => {
        const id = item.properties.name;
        const formItem = _this.selectComponent(`#${id}`);
        if (formItem) {
          item.validatorData(params);
        } else {
          throw new Error(`表单项不存在name:${id}`);
        }
        this._errors[id] = item.data.errors;
        formErrors = formErrors.concat(item.data.errors);
      }, true);
      callback && callback(formErrors);
      return formErrors;
    },

    _getValues() {
      let params = {};
      let _this = wx.lin._instantiation;

      this._forEachNodes(item => {
        const _id = item.properties.name;
        const formItem = _this.selectComponent(`#${_id}`);
        if (formItem) {
          params[_id] = formItem.getValues();
        }
      });
      return params;
    },

    submit() {
      let errors = this.data.isSubmitValidate ? this._validateForm() : [];
      this.triggerEvent('linsubmit', {
        values: this._getValues(),
        errors: this.data.isSubmitValidate ? this._errors : {},
        isValidate: errors.length === 0
      });
    },
    reset() {
      let _this = wx.lin._instantiation;
      this._forEachNodes((item) => {
        item.setData({
          errorText: ''
        });
        const _id = item.properties.name;
        const formItem = _this.selectComponent(`#${_id}`);
        if (formItem) {
          formItem.reset();
        }
      });
      eventUtil.emit(this, 'linreset');
    }
  }
});

关键代码

  wx.lin.validateForm = function (name, callback) {
        wx.lin.forms[name]._validateForm(callback);
      };

_validateForm(callback) {
      let _this = wx.lin._instantiation;
      // 校验name的rule
      let formErrors = [];
      let params = this._getValues();
      this._forEachNodes(item => {
        const id = item.properties.name;
        const formItem = _this.selectComponent(`#${id}`);
        if (formItem) {
          item.validatorData(params);
        } else {
          throw new Error(`表单项不存在name:${id}`);
        }
        this._errors[id] = item.data.errors;
        formErrors = formErrors.concat(item.data.errors);
      }, true);
      callback && callback(formErrors);
      return formErrors;
    },

使用方法


   wx.lin.validateForm('FormName',(errs)=>{
      console.log(errs)
    });

随时可以检测当前还有多少个错误

CHEN-J-H commented 2 years ago

第一次在github发言,菜鸟码农,不太懂规矩,纯属想分享所得,有破坏规矩敬请谅解,希望作者尽早提供官方picker

smileShirmy commented 2 years ago

感谢建议