¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="uni-forms"> |
| | | <form> |
| | | <slot></slot> |
| | | </form> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import Validator from './validate.js'; |
| | | import { |
| | | deepCopy, |
| | | getValue, |
| | | isRequiredField, |
| | | setDataValue, |
| | | getDataValue, |
| | | realName, |
| | | isRealName, |
| | | rawData, |
| | | isEqual |
| | | } from './utils.js' |
| | | |
| | | // #ifndef VUE3 |
| | | // åç»ä¼æ
¢æ
¢åºå¼è¿ä¸ªæ¹æ³ |
| | | import Vue from 'vue'; |
| | | Vue.prototype.binddata = function(name, value, formName) { |
| | | if (formName) { |
| | | this.$refs[formName].setValue(name, value); |
| | | } else { |
| | | let formVm; |
| | | for (let i in this.$refs) { |
| | | const vm = this.$refs[i]; |
| | | if (vm && vm.$options && vm.$options.name === 'uniForms') { |
| | | formVm = vm; |
| | | break; |
| | | } |
| | | } |
| | | if (!formVm) return console.error('å½å uni-froms ç»ä»¶ç¼ºå° ref 屿§'); |
| | | formVm.setValue(name, value); |
| | | } |
| | | }; |
| | | // #endif |
| | | /** |
| | | * Forms 表å |
| | | * @description ç±è¾å
¥æ¡ãéæ©å¨ãåéæ¡ãå¤éæ¡çæ§ä»¶ç»æï¼ç¨ä»¥æ¶éãæ ¡éªãæäº¤æ°æ® |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=2773 |
| | | * @property {Object} rules è¡¨åæ ¡éªè§å |
| | | * @property {String} validateTrigger = [bind|submit|blur] æ ¡éªè§¦å卿¹å¼ é»è®¤ submit |
| | | * @value bind åçååæ¶è§¦å |
| | | * @value submit æäº¤æ¶è§¦å |
| | | * @value blur 失å»ç¦ç¹æ¶è§¦å |
| | | * @property {String} labelPosition = [top|left] label ä½ç½® é»è®¤ left |
| | | * @value top 顶鍿¾ç¤º label |
| | | * @value left 左侧æ¾ç¤º label |
| | | * @property {String} labelWidth label 宽度ï¼é»è®¤ 65px |
| | | * @property {String} labelAlign = [left|center|right] label å±
䏿¹å¼ é»è®¤ left |
| | | * @value left label 左侧æ¾ç¤º |
| | | * @value center label å±
ä¸ |
| | | * @value right label å³ä¾§å¯¹é½ |
| | | * @property {String} errShowType = [undertext|toast|modal] æ ¡éªéè¯¯ä¿¡æ¯æç¤ºæ¹å¼ |
| | | * @value undertext é误信æ¯å¨åºé¨æ¾ç¤º |
| | | * @value toast é误信æ¯toastæ¾ç¤º |
| | | * @value modal é误信æ¯modalæ¾ç¤º |
| | | * @event {Function} submit æäº¤æ¶è§¦å |
| | | * @event {Function} validate æ ¡éªç»æåçåå触å |
| | | */ |
| | | export default { |
| | | name: 'uniForms', |
| | | emits: ['validate', 'submit'], |
| | | options: { |
| | | virtualHost: true |
| | | }, |
| | | props: { |
| | | // å³å°å¼ç¨ |
| | | value: { |
| | | type: Object, |
| | | default () { |
| | | return null; |
| | | } |
| | | }, |
| | | // vue3 æ¿æ¢ value 屿§ |
| | | modelValue: { |
| | | type: Object, |
| | | default () { |
| | | return null; |
| | | } |
| | | }, |
| | | // 1.4.0 å¼å§å°ä¸æ¯æ v-model ï¼ä¸åºå¼ value å modelValue |
| | | model: { |
| | | type: Object, |
| | | default () { |
| | | return null; |
| | | } |
| | | }, |
| | | // è¡¨åæ ¡éªè§å |
| | | rules: { |
| | | type: Object, |
| | | default () { |
| | | return {}; |
| | | } |
| | | }, |
| | | //æ ¡éªéè¯¯ä¿¡æ¯æç¤ºæ¹å¼ é»è®¤ undertext åå¼ [undertext|toast|modal] |
| | | errShowType: { |
| | | type: String, |
| | | default: 'undertext' |
| | | }, |
| | | // æ ¡éªè§¦å卿¹å¼ é»è®¤ bind åå¼ [bind|submit] |
| | | validateTrigger: { |
| | | type: String, |
| | | default: 'submit' |
| | | }, |
| | | // label ä½ç½®ï¼é»è®¤ left åå¼ top/left |
| | | labelPosition: { |
| | | type: String, |
| | | default: 'left' |
| | | }, |
| | | // label 宽度 |
| | | labelWidth: { |
| | | type: [String, Number], |
| | | default: '' |
| | | }, |
| | | // label å±
䏿¹å¼ï¼é»è®¤ left åå¼ left/center/right |
| | | labelAlign: { |
| | | type: String, |
| | | default: 'left' |
| | | }, |
| | | border: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | provide() { |
| | | return { |
| | | uniForm: this |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // è¡¨åæ¬å°å¼çè®°å½ï¼ä¸åºè¯¥ä¸ä¼ å¦çå¼è¿è¡å
³è |
| | | formData: {}, |
| | | formRules: {} |
| | | }; |
| | | }, |
| | | computed: { |
| | | // è®¡ç®æ°æ®æºååç |
| | | localData() { |
| | | const localVal = this.model || this.modelValue || this.value |
| | | if (localVal) { |
| | | return deepCopy(localVal) |
| | | } |
| | | return {} |
| | | } |
| | | }, |
| | | watch: { |
| | | // ç嬿°æ®åå ,ææ¶ä¸ä½¿ç¨ï¼éè¦åç¬èµå¼ |
| | | // localData: {}, |
| | | // çå¬è§ååå |
| | | rules: { |
| | | handler: function(val, oldVal) { |
| | | this.setRules(val) |
| | | }, |
| | | deep: true, |
| | | immediate: true |
| | | } |
| | | }, |
| | | created() { |
| | | // #ifdef VUE3 |
| | | let getbinddata = getApp().$vm.$.appContext.config.globalProperties.binddata |
| | | if (!getbinddata) { |
| | | getApp().$vm.$.appContext.config.globalProperties.binddata = function(name, value, formName) { |
| | | if (formName) { |
| | | this.$refs[formName].setValue(name, value); |
| | | } else { |
| | | let formVm; |
| | | for (let i in this.$refs) { |
| | | const vm = this.$refs[i]; |
| | | if (vm && vm.$options && vm.$options.name === 'uniForms') { |
| | | formVm = vm; |
| | | break; |
| | | } |
| | | } |
| | | if (!formVm) return console.error('å½å uni-froms ç»ä»¶ç¼ºå° ref 屿§'); |
| | | formVm.setValue(name, value); |
| | | } |
| | | } |
| | | } |
| | | // #endif |
| | | |
| | | // åç»ä»¶å®ä¾æ°ç» |
| | | this.childrens = [] |
| | | // TODO å
¼å®¹æ§ç uni-data-picker ,æ°çæ¬ä¸æ æï¼åªæ¯é¿å
æ¥é |
| | | this.inputChildrens = [] |
| | | this.setRules(this.rules) |
| | | }, |
| | | methods: { |
| | | /** |
| | | * å¤é¨è°ç¨æ¹æ³ |
| | | * 设置è§å ï¼ä¸»è¦ç¨äºå°ç¨åºèªå®ä¹æ£éªè§å |
| | | * @param {Array} rules è§åæºæ°æ® |
| | | */ |
| | | setRules(rules) { |
| | | // TODO æå¯è½åç»ä»¶åå¹¶è§åçæ¶æºæ¯è¿ä¸ªè¦æ©ï¼æä»¥éè¦å并对象 ï¼è䏿¯ç´æ¥èµå¼ï¼å¯è½ä¼è¢«è¦ç |
| | | this.formRules = Object.assign({}, this.formRules, rules) |
| | | // åå§åæ ¡éªå½æ° |
| | | this.validator = new Validator(rules); |
| | | }, |
| | | |
| | | /** |
| | | * å¤é¨è°ç¨æ¹æ³ |
| | | * è®¾ç½®æ°æ®ï¼ç¨äºè®¾ç½®è¡¨åæ°æ®ï¼å
¬å¼ç»ç¨æ·ä½¿ç¨ ï¼ ä¸æ¯æå¨å¨æè¡¨åä¸ä½¿ç¨ |
| | | * @param {Object} key |
| | | * @param {Object} value |
| | | */ |
| | | setValue(key, value) { |
| | | let example = this.childrens.find(child => child.name === key); |
| | | if (!example) return null; |
| | | this.formData[key] = getValue(key, value, (this.formRules[key] && this.formRules[key].rules) || []) |
| | | return example.onFieldChange(this.formData[key]); |
| | | }, |
| | | |
| | | /** |
| | | * å¤é¨è°ç¨æ¹æ³ |
| | | * æå¨æäº¤æ ¡éªè¡¨å |
| | | * 对æ´ä¸ªè¡¨åè¿è¡æ ¡éªçæ¹æ³ï¼åæ°ä¸ºä¸ä¸ªåè°å½æ°ã |
| | | * @param {Array} keepitem ä¿çä¸å䏿 ¡éªçåæ®µ |
| | | * @param {type} callback æ¹æ³åè° |
| | | */ |
| | | validate(keepitem, callback) { |
| | | return this.checkAll(this.formData, keepitem, callback); |
| | | }, |
| | | |
| | | /** |
| | | * å¤é¨è°ç¨æ¹æ³ |
| | | * é¨åè¡¨åæ ¡éª |
| | | * @param {Array|String} props éè¦æ ¡éªçåæ®µ |
| | | * @param {Function} åè°å½æ° |
| | | */ |
| | | validateField(props = [], callback) { |
| | | props = [].concat(props); |
| | | let invalidFields = {}; |
| | | this.childrens.forEach(item => { |
| | | const name = realName(item.name) |
| | | if (props.indexOf(name) !== -1) { |
| | | invalidFields = Object.assign({}, invalidFields, { |
| | | [name]: this.formData[name] |
| | | }); |
| | | } |
| | | }); |
| | | return this.checkAll(invalidFields, [], callback); |
| | | }, |
| | | |
| | | /** |
| | | * å¤é¨è°ç¨æ¹æ³ |
| | | * ç§»é¤è¡¨åé¡¹çæ ¡éªç»æãä¼ å
¥å¾
ç§»é¤ç表å项ç prop 屿§æè
prop ç»æçæ°ç»ï¼å¦ä¸ä¼ åç§»é¤æ´ä¸ªè¡¨åçæ ¡éªç»æ |
| | | * @param {Array|String} props éè¦ç§»é¤æ ¡éªçåæ®µ ï¼ä¸å¡«ä¸ºææ |
| | | */ |
| | | clearValidate(props = []) { |
| | | props = [].concat(props); |
| | | this.childrens.forEach(item => { |
| | | if (props.length === 0) { |
| | | item.errMsg = ''; |
| | | } else { |
| | | const name = realName(item.name) |
| | | if (props.indexOf(name) !== -1) { |
| | | item.errMsg = ''; |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * å¤é¨è°ç¨æ¹æ³ ï¼å³å°åºå¼ |
| | | * æå¨æäº¤æ ¡éªè¡¨å |
| | | * 对æ´ä¸ªè¡¨åè¿è¡æ ¡éªçæ¹æ³ï¼åæ°ä¸ºä¸ä¸ªåè°å½æ°ã |
| | | * @param {Array} keepitem ä¿çä¸å䏿 ¡éªçåæ®µ |
| | | * @param {type} callback æ¹æ³åè° |
| | | */ |
| | | submit(keepitem, callback, type) { |
| | | for (let i in this.dataValue) { |
| | | const itemData = this.childrens.find(v => v.name === i); |
| | | if (itemData) { |
| | | if (this.formData[i] === undefined) { |
| | | this.formData[i] = this._getValue(i, this.dataValue[i]); |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (!type) { |
| | | console.warn('submit æ¹æ³å³å°åºå¼ï¼è¯·ä½¿ç¨validateæ¹æ³ä»£æ¿ï¼'); |
| | | } |
| | | |
| | | return this.checkAll(this.formData, keepitem, callback, 'submit'); |
| | | }, |
| | | |
| | | // æ ¡éªææ |
| | | async checkAll(invalidFields, keepitem, callback, type) { |
| | | // ä¸å卿 ¡éªè§å ï¼ååæ¢æ ¡éªæµç¨ |
| | | if (!this.validator) return |
| | | let childrens = [] |
| | | // å¤çå䏿 ¡éªçitemå®ä¾ |
| | | for (let i in invalidFields) { |
| | | const item = this.childrens.find(v => realName(v.name) === i) |
| | | if (item) { |
| | | childrens.push(item) |
| | | } |
| | | } |
| | | |
| | | // 妿validate第ä¸ä¸ªåæ°æ¯funciont ,é£å°±èµ°åè° |
| | | if (!callback && typeof keepitem === 'function') { |
| | | callback = keepitem; |
| | | } |
| | | |
| | | let promise; |
| | | // 妿ä¸åå¨åè°ï¼é£ä¹ä½¿ç¨ Promise æ¹å¼è¿å |
| | | if (!callback && typeof callback !== 'function' && Promise) { |
| | | promise = new Promise((resolve, reject) => { |
| | | callback = function(valid, invalidFields) { |
| | | !valid ? resolve(invalidFields) : reject(valid); |
| | | }; |
| | | }); |
| | | } |
| | | |
| | | let results = []; |
| | | // é¿å
å¼ç¨éä¹± ï¼å»ºè®®æ·è´å¯¹è±¡å¤ç |
| | | let tempFormData = JSON.parse(JSON.stringify(invalidFields)) |
| | | // ææåç»ä»¶å䏿 ¡éª,ä½¿ç¨ for å¯ä»¥ä½¿ç¨ awiat |
| | | for (let i in childrens) { |
| | | const child = childrens[i] |
| | | let name = realName(child.name); |
| | | const result = await child.onFieldChange(tempFormData[name]); |
| | | if (result) { |
| | | results.push(result); |
| | | // toast ,modal åªéè¦æ§è¡ç¬¬ä¸æ¬¡å°±å¯ä»¥ |
| | | if (this.errShowType === 'toast' || this.errShowType === 'modal') break; |
| | | } |
| | | } |
| | | |
| | | |
| | | if (Array.isArray(results)) { |
| | | if (results.length === 0) results = null; |
| | | } |
| | | if (Array.isArray(keepitem)) { |
| | | keepitem.forEach(v => { |
| | | let vName = realName(v); |
| | | let value = getDataValue(v, this.localData) |
| | | if (value !== undefined) { |
| | | tempFormData[vName] = value |
| | | } |
| | | }); |
| | | } |
| | | |
| | | // TODO submit å³å°åºå¼ |
| | | if (type === 'submit') { |
| | | this.$emit('submit', { |
| | | detail: { |
| | | value: tempFormData, |
| | | errors: results |
| | | } |
| | | }); |
| | | } else { |
| | | this.$emit('validate', results); |
| | | } |
| | | |
| | | // const resetFormData = rawData(tempFormData, this.localData, this.name) |
| | | let resetFormData = {} |
| | | resetFormData = rawData(tempFormData, this.name) |
| | | callback && typeof callback === 'function' && callback(results, resetFormData); |
| | | |
| | | if (promise && callback) { |
| | | return promise; |
| | | } else { |
| | | return null; |
| | | } |
| | | |
| | | }, |
| | | |
| | | /** |
| | | * è¿åvalidateäºä»¶ |
| | | * @param {Object} result |
| | | */ |
| | | validateCheck(result) { |
| | | this.$emit('validate', result); |
| | | }, |
| | | _getValue: getValue, |
| | | _isRequiredField: isRequiredField, |
| | | _setDataValue: setDataValue, |
| | | _getDataValue: getDataValue, |
| | | _realName: realName, |
| | | _isRealName: isRealName, |
| | | _isEqual: isEqual |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | .uni-forms {} |
| | | </style> |