| | |
| | | <template> |
| | | <view class="uni-forms" :class="{ 'uni-forms--top': !border }"> |
| | | <form @submit.stop="submitForm" @reset="resetForm"> |
| | | <slot></slot> |
| | | </form> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | // #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 |
| | | |
| | | |
| | | |
| | | import Validator from './validate.js'; |
| | | /** |
| | | * Forms 表单 |
| | | * @description 由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据 |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=2773 |
| | | * @property {Object} rules 表单校验规则 |
| | | * @property {String} validateTrigger = [bind|submit] 校验触发器方式 默认 submit |
| | | * @value bind 发生变化时触发 |
| | | * @value submit 提交时触发 |
| | | * @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 提交时触发 |
| | | */ |
| | | |
| | | export default { |
| | | name: 'uniForms', |
| | | components: {}, |
| | | emits:['input','reset','validate','submit'], |
| | | props: { |
| | | // 即将弃用 |
| | | value: { |
| | | type: Object, |
| | | default () { |
| | | return {}; |
| | | } |
| | | }, |
| | | // 替换 value 属性 |
| | | modelValue: { |
| | | type: Object, |
| | | default () { |
| | | return {}; |
| | | } |
| | | }, |
| | | // 表单校验规则 |
| | | rules: { |
| | | type: Object, |
| | | default () { |
| | | return {}; |
| | | } |
| | | }, |
| | | // 校验触发器方式,默认 关闭 |
| | | validateTrigger: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | // label 位置,可选值 top/left |
| | | labelPosition: { |
| | | type: String, |
| | | default: 'left' |
| | | }, |
| | | // label 宽度,单位 px |
| | | labelWidth: { |
| | | type: [String, Number], |
| | | default: '' |
| | | }, |
| | | // label 居中方式,可选值 left/center/right |
| | | labelAlign: { |
| | | type: String, |
| | | default: 'left' |
| | | }, |
| | | errShowType: { |
| | | type: String, |
| | | default: 'undertext' |
| | | }, |
| | | border: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | formData: {} |
| | | }; |
| | | }, |
| | | computed: { |
| | | dataValue() { |
| | | if (JSON.stringify(this.modelValue) === '{}') { |
| | | return this.value |
| | | } else { |
| | | return this.modelValue |
| | | } |
| | | } |
| | | }, |
| | | watch: { |
| | | rules(newVal) { |
| | | // 如果规则发生变化,要初始化组件 |
| | | this.init(newVal); |
| | | }, |
| | | labelPosition() { |
| | | this.childrens.forEach(vm => { |
| | | vm.init() |
| | | }) |
| | | } |
| | | }, |
| | | 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 |
| | | |
| | | // 存放watch 监听数组 |
| | | this.unwatchs = []; |
| | | // 存放子组件数组 |
| | | this.childrens = []; |
| | | // 存放 easyInput 组件 |
| | | this.inputChildrens = []; |
| | | // 存放 dataCheckbox 组件 |
| | | this.checkboxChildrens = []; |
| | | // 存放规则 |
| | | this.formRules = []; |
| | | this.init(this.rules); |
| | | }, |
| | | // mounted() { |
| | | // this.init(this.rules) |
| | | // }, |
| | | methods: { |
| | | init(formRules) { |
| | | // 判断是否有规则 |
| | | if (Object.keys(formRules).length === 0) { |
| | | this.formData = this.dataValue |
| | | return |
| | | }; |
| | | this.formRules = formRules; |
| | | this.validator = new Validator(formRules); |
| | | this.registerWatch(); |
| | | }, |
| | | // 监听 watch |
| | | registerWatch() { |
| | | // 取消监听,避免多次调用 init 重复执行 $watch |
| | | this.unwatchs.forEach(v => v()); |
| | | this.childrens.forEach((v) => { |
| | | v.init() |
| | | }) |
| | | // watch 每个属性 ,需要知道具体那个属性发变化 |
| | | Object.keys(this.dataValue).forEach(key => { |
| | | let watch = this.$watch( |
| | | 'dataValue.' + key, |
| | | value => { |
| | | if (!value) return |
| | | // 如果是对象 ,则平铺内容 |
| | | if (value.toString() === '[object Object]') { |
| | | for (let i in value) { |
| | | let name = `${key}[${i}]`; |
| | | this.formData[name] = this._getValue(name, value[i]); |
| | | } |
| | | } else { |
| | | this.formData[key] = this._getValue(key, value); |
| | | } |
| | | }, |
| | | { |
| | | deep: true, |
| | | immediate: true |
| | | } |
| | | ); |
| | | this.unwatchs.push(watch); |
| | | }); |
| | | }, |
| | | /** |
| | | * 公开给用户使用 |
| | | * 设置校验规则 |
| | | * @param {Object} formRules |
| | | */ |
| | | setRules(formRules) { |
| | | this.init(formRules); |
| | | }, |
| | | /** |
| | | * 公开给用户使用 |
| | | * 设置自定义表单组件 value 值 |
| | | * @param {String} name 字段名称 |
| | | * @param {String} value 字段值 |
| | | */ |
| | | setValue(name, value, callback) { |
| | | let example = this.childrens.find(child => child.name === name); |
| | | if (!example) return null; |
| | | value = this._getValue(example.name, value); |
| | | this.formData[name] = value; |
| | | example.val = value; |
| | | return example.triggerCheck(value, callback); |
| | | }, |
| | | |
| | | /** |
| | | * 表单重置 |
| | | * @param {Object} event |
| | | */ |
| | | resetForm(event) { |
| | | this.childrens.forEach(item => { |
| | | item.errMsg = ''; |
| | | const inputComp = this.inputChildrens.find(child => child.rename === item.name); |
| | | if (inputComp) { |
| | | inputComp.errMsg = ''; |
| | | // fix by mehaotian 不触发其他组件的 setValue |
| | | inputComp.is_reset = true |
| | | inputComp.$emit('input', inputComp.multiple ? [] : ''); |
| | | inputComp.$emit('update:modelValue', inputComp.multiple ? [] : ''); |
| | | } |
| | | }); |
| | | |
| | | this.childrens.forEach(item => { |
| | | if (item.name) { |
| | | this.formData[item.name] = this._getValue(item.name, ''); |
| | | } |
| | | }); |
| | | |
| | | this.$emit('reset', event); |
| | | }, |
| | | |
| | | /** |
| | | * 触发表单校验,通过 @validate 获取 |
| | | * @param {Object} validate |
| | | */ |
| | | validateCheck(validate) { |
| | | if (validate === null) validate = null; |
| | | this.$emit('validate', validate); |
| | | }, |
| | | /** |
| | | * 校验所有或者部分表单 |
| | | */ |
| | | async validateAll(invalidFields, type, keepitem, callback) { |
| | | let childrens = [] |
| | | for (let i in invalidFields) { |
| | | const item = this.childrens.find(v => v.name === i) |
| | | if (item) { |
| | | childrens.push(item) |
| | | } |
| | | } |
| | | |
| | | if (!callback && typeof keepitem === 'function') { |
| | | callback = keepitem; |
| | | } |
| | | |
| | | let promise; |
| | | if (!callback && typeof callback !== 'function' && Promise) { |
| | | promise = new Promise((resolve, reject) => { |
| | | callback = function(valid, invalidFields) { |
| | | !valid ? resolve(invalidFields) : reject(valid); |
| | | }; |
| | | }); |
| | | } |
| | | |
| | | let results = []; |
| | | let newFormData = {}; |
| | | if (this.validator) { |
| | | for (let key in childrens) { |
| | | const child = childrens[key]; |
| | | let name = child.isArray ? child.arrayField : child.name; |
| | | if (child.isArray) { |
| | | if (child.name.indexOf('[') !== -1 && child.name.indexOf(']') !== -1) { |
| | | const fieldData = child.name.split('['); |
| | | const fieldName = fieldData[0]; |
| | | const fieldValue = fieldData[1].replace(']', ''); |
| | | if (!newFormData[fieldName]) { |
| | | newFormData[fieldName] = {}; |
| | | } |
| | | newFormData[fieldName][fieldValue] = this._getValue(name, invalidFields[name]); |
| | | } |
| | | } else { |
| | | newFormData[name] = this._getValue(name, invalidFields[name]); |
| | | } |
| | | const result = await child.triggerCheck(invalidFields[name], true); |
| | | if (result) { |
| | | results.push(result); |
| | | if (this.errShowType === 'toast' || this.errShowType === 'modal') break; |
| | | } |
| | | } |
| | | } else { |
| | | newFormData = invalidFields |
| | | } |
| | | if (Array.isArray(results)) { |
| | | if (results.length === 0) results = null; |
| | | } |
| | | |
| | | if (Array.isArray(keepitem)) { |
| | | keepitem.forEach(v => { |
| | | newFormData[v] = this.dataValue[v]; |
| | | }); |
| | | } |
| | | |
| | | if (type === 'submit') { |
| | | this.$emit('submit', { |
| | | detail: { |
| | | value: newFormData, |
| | | errors: results |
| | | } |
| | | }); |
| | | } else { |
| | | this.$emit('validate', results); |
| | | } |
| | | |
| | | callback && typeof callback === 'function' && callback(results, newFormData); |
| | | |
| | | if (promise && callback) { |
| | | return promise; |
| | | } else { |
| | | return null; |
| | | } |
| | | }, |
| | | submitForm() {}, |
| | | /** |
| | | * 外部调用方法 |
| | | * 手动提交校验表单 |
| | | * 对整个表单进行校验的方法,参数为一个回调函数。 |
| | | */ |
| | | 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.validateAll(this.formData, 'submit', keepitem, callback); |
| | | }, |
| | | |
| | | /** |
| | | * 外部调用方法 |
| | | * 校验表单 |
| | | * 对整个表单进行校验的方法,参数为一个回调函数。 |
| | | */ |
| | | validate(keepitem, callback) { |
| | | return this.submit(keepitem, callback, true); |
| | | }, |
| | | |
| | | /** |
| | | * 部分表单校验 |
| | | * @param {Object} props |
| | | * @param {Object} cb |
| | | */ |
| | | validateField(props, callback) { |
| | | props = [].concat(props); |
| | | let invalidFields = {}; |
| | | this.childrens.forEach(item => { |
| | | if (props.indexOf(item.name) !== -1) { |
| | | invalidFields = Object.assign({}, invalidFields, { |
| | | [item.name]: this.formData[item.name] |
| | | }); |
| | | } |
| | | }); |
| | | return this.validateAll(invalidFields, 'submit', [], callback); |
| | | }, |
| | | |
| | | /** |
| | | * 对整个表单进行重置,将所有字段值重置为初始值并移除校验结果 |
| | | */ |
| | | resetFields() { |
| | | this.resetForm(); |
| | | }, |
| | | |
| | | /** |
| | | * 移除表单项的校验结果。传入待移除的表单项的 prop 属性或者 prop 组成的数组,如不传则移除整个表单的校验结果 |
| | | */ |
| | | clearValidate(props) { |
| | | props = [].concat(props); |
| | | this.childrens.forEach(item => { |
| | | const inputComp = this.inputChildrens.find(child => child.rename === item.name); |
| | | if (props.length === 0) { |
| | | item.errMsg = ''; |
| | | if (inputComp) { |
| | | inputComp.errMsg = ''; |
| | | } |
| | | } else { |
| | | if (props.indexOf(item.name) !== -1) { |
| | | item.errMsg = ''; |
| | | if (inputComp) { |
| | | inputComp.errMsg = ''; |
| | | } |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | /** |
| | | * 把 value 转换成指定的类型 |
| | | * @param {Object} key |
| | | * @param {Object} value |
| | | */ |
| | | _getValue(key, value) { |
| | | const rules = (this.formRules[key] && this.formRules[key].rules) || []; |
| | | const isRuleNum = rules.find(val => val.format && this.type_filter(val.format)); |
| | | const isRuleBool = rules.find(val => (val.format && val.format === 'boolean') || val.format === 'bool'); |
| | | // 输入值为 number |
| | | if (isRuleNum) { |
| | | value = isNaN(value) ? value : value === '' || value === null ? null : Number(value); |
| | | } |
| | | // 简单判断真假值 |
| | | if (isRuleBool) { |
| | | value = !value ? false : true; |
| | | } |
| | | return value; |
| | | }, |
| | | /** |
| | | * 过滤数字类型 |
| | | * @param {Object} format |
| | | */ |
| | | type_filter(format) { |
| | | return format === 'int' || format === 'double' || format === 'number' || format === 'timestamp'; |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" > |
| | | .uni-forms { |
| | | // overflow: hidden; |
| | | // padding: 10px 15px; |
| | | } |
| | | |
| | | .uni-forms--top { |
| | | // padding: 10px 15px; |
| | | // padding-top: 22px; |
| | | } |
| | | </style> |
| | | <template>
|
| | | <view class="uni-forms" :class="{ 'uni-forms--top': !border }">
|
| | | <form @submit.stop="submitForm" @reset="resetForm">
|
| | | <slot></slot>
|
| | | </form>
|
| | | </view>
|
| | | </template>
|
| | |
|
| | | <script>
|
| | | // #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
|
| | |
|
| | |
|
| | |
|
| | | import Validator from './validate.js';
|
| | | /**
|
| | | * Forms 表单
|
| | | * @description 由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据
|
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=2773
|
| | | * @property {Object} rules 表单校验规则
|
| | | * @property {String} validateTrigger = [bind|submit] 校验触发器方式 默认 submit
|
| | | * @value bind 发生变化时触发
|
| | | * @value submit 提交时触发
|
| | | * @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 提交时触发
|
| | | */
|
| | |
|
| | | export default {
|
| | | name: 'uniForms',
|
| | | components: {},
|
| | | emits:['input','reset','validate','submit'],
|
| | | props: {
|
| | | // 即将弃用
|
| | | value: {
|
| | | type: Object,
|
| | | default () {
|
| | | return {};
|
| | | }
|
| | | },
|
| | | // 替换 value 属性
|
| | | modelValue: {
|
| | | type: Object,
|
| | | default () {
|
| | | return {};
|
| | | }
|
| | | },
|
| | | // 表单校验规则
|
| | | rules: {
|
| | | type: Object,
|
| | | default () {
|
| | | return {};
|
| | | }
|
| | | },
|
| | | // 校验触发器方式,默认 关闭
|
| | | validateTrigger: {
|
| | | type: String,
|
| | | default: ''
|
| | | },
|
| | | // label 位置,可选值 top/left
|
| | | labelPosition: {
|
| | | type: String,
|
| | | default: 'left'
|
| | | },
|
| | | // label 宽度,单位 px
|
| | | labelWidth: {
|
| | | type: [String, Number],
|
| | | default: ''
|
| | | },
|
| | | // label 居中方式,可选值 left/center/right
|
| | | labelAlign: {
|
| | | type: String,
|
| | | default: 'left'
|
| | | },
|
| | | errShowType: {
|
| | | type: String,
|
| | | default: 'undertext'
|
| | | },
|
| | | border: {
|
| | | type: Boolean,
|
| | | default: false
|
| | | }
|
| | | },
|
| | | data() {
|
| | | return {
|
| | | formData: {}
|
| | | };
|
| | | },
|
| | | computed: {
|
| | | dataValue() {
|
| | | if (JSON.stringify(this.modelValue) === '{}') {
|
| | | return this.value
|
| | | } else {
|
| | | return this.modelValue
|
| | | }
|
| | | }
|
| | | },
|
| | | watch: {
|
| | | rules(newVal) {
|
| | | // 如果规则发生变化,要初始化组件
|
| | | this.init(newVal);
|
| | | },
|
| | | labelPosition() {
|
| | | this.childrens.forEach(vm => {
|
| | | vm.init()
|
| | | })
|
| | | }
|
| | | },
|
| | | 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
|
| | |
|
| | | // 存放watch 监听数组
|
| | | this.unwatchs = [];
|
| | | // 存放子组件数组
|
| | | this.childrens = [];
|
| | | // 存放 easyInput 组件
|
| | | this.inputChildrens = [];
|
| | | // 存放 dataCheckbox 组件
|
| | | this.checkboxChildrens = [];
|
| | | // 存放规则
|
| | | this.formRules = [];
|
| | | this.init(this.rules);
|
| | | },
|
| | | // mounted() {
|
| | | // this.init(this.rules)
|
| | | // },
|
| | | methods: {
|
| | | init(formRules) {
|
| | | // 判断是否有规则
|
| | | if (Object.keys(formRules).length === 0) {
|
| | | this.formData = this.dataValue
|
| | | return
|
| | | };
|
| | | this.formRules = formRules;
|
| | | this.validator = new Validator(formRules);
|
| | | this.registerWatch();
|
| | | },
|
| | | // 监听 watch
|
| | | registerWatch() {
|
| | | // 取消监听,避免多次调用 init 重复执行 $watch
|
| | | this.unwatchs.forEach(v => v());
|
| | | this.childrens.forEach((v) => {
|
| | | v.init()
|
| | | })
|
| | | // watch 每个属性 ,需要知道具体那个属性发变化
|
| | | Object.keys(this.dataValue).forEach(key => {
|
| | | let watch = this.$watch(
|
| | | 'dataValue.' + key,
|
| | | value => {
|
| | | if (!value) return
|
| | | // 如果是对象 ,则平铺内容
|
| | | if (value.toString() === '[object Object]') {
|
| | | for (let i in value) {
|
| | | let name = `${key}[${i}]`;
|
| | | this.formData[name] = this._getValue(name, value[i]);
|
| | | }
|
| | | } else {
|
| | | this.formData[key] = this._getValue(key, value);
|
| | | }
|
| | | },
|
| | | {
|
| | | deep: true,
|
| | | immediate: true
|
| | | }
|
| | | );
|
| | | this.unwatchs.push(watch);
|
| | | });
|
| | | },
|
| | | /**
|
| | | * 公开给用户使用
|
| | | * 设置校验规则
|
| | | * @param {Object} formRules
|
| | | */
|
| | | setRules(formRules) {
|
| | | this.init(formRules);
|
| | | },
|
| | | /**
|
| | | * 公开给用户使用
|
| | | * 设置自定义表单组件 value 值
|
| | | * @param {String} name 字段名称
|
| | | * @param {String} value 字段值
|
| | | */
|
| | | setValue(name, value, callback) {
|
| | | let example = this.childrens.find(child => child.name === name);
|
| | | if (!example) return null;
|
| | | value = this._getValue(example.name, value);
|
| | | this.formData[name] = value;
|
| | | example.val = value;
|
| | | return example.triggerCheck(value, callback);
|
| | | },
|
| | |
|
| | | /**
|
| | | * 表单重置
|
| | | * @param {Object} event
|
| | | */
|
| | | resetForm(event) {
|
| | | this.childrens.forEach(item => {
|
| | | item.errMsg = '';
|
| | | const inputComp = this.inputChildrens.find(child => child.rename === item.name);
|
| | | if (inputComp) {
|
| | | inputComp.errMsg = '';
|
| | | // fix by mehaotian 不触发其他组件的 setValue
|
| | | inputComp.is_reset = true
|
| | | inputComp.$emit('input', inputComp.multiple ? [] : '');
|
| | | inputComp.$emit('update:modelValue', inputComp.multiple ? [] : '');
|
| | | }
|
| | | });
|
| | |
|
| | | this.childrens.forEach(item => {
|
| | | if (item.name) {
|
| | | this.formData[item.name] = this._getValue(item.name, '');
|
| | | }
|
| | | });
|
| | |
|
| | | this.$emit('reset', event);
|
| | | },
|
| | |
|
| | | /**
|
| | | * 触发表单校验,通过 @validate 获取
|
| | | * @param {Object} validate
|
| | | */
|
| | | validateCheck(validate) {
|
| | | if (validate === null) validate = null;
|
| | | this.$emit('validate', validate);
|
| | | },
|
| | | /**
|
| | | * 校验所有或者部分表单
|
| | | */
|
| | | async validateAll(invalidFields, type, keepitem, callback) {
|
| | | let childrens = []
|
| | | for (let i in invalidFields) {
|
| | | const item = this.childrens.find(v => v.name === i)
|
| | | if (item) {
|
| | | childrens.push(item)
|
| | | }
|
| | | }
|
| | |
|
| | | if (!callback && typeof keepitem === 'function') {
|
| | | callback = keepitem;
|
| | | }
|
| | |
|
| | | let promise;
|
| | | if (!callback && typeof callback !== 'function' && Promise) {
|
| | | promise = new Promise((resolve, reject) => {
|
| | | callback = function(valid, invalidFields) {
|
| | | !valid ? resolve(invalidFields) : reject(valid);
|
| | | };
|
| | | });
|
| | | }
|
| | |
|
| | | let results = [];
|
| | | let newFormData = {};
|
| | | if (this.validator) {
|
| | | for (let key in childrens) {
|
| | | const child = childrens[key];
|
| | | let name = child.isArray ? child.arrayField : child.name;
|
| | | if (child.isArray) {
|
| | | if (child.name.indexOf('[') !== -1 && child.name.indexOf(']') !== -1) {
|
| | | const fieldData = child.name.split('[');
|
| | | const fieldName = fieldData[0];
|
| | | const fieldValue = fieldData[1].replace(']', '');
|
| | | if (!newFormData[fieldName]) {
|
| | | newFormData[fieldName] = {};
|
| | | }
|
| | | newFormData[fieldName][fieldValue] = this._getValue(name, invalidFields[name]);
|
| | | }
|
| | | } else {
|
| | | newFormData[name] = this._getValue(name, invalidFields[name]);
|
| | | }
|
| | | const result = await child.triggerCheck(invalidFields[name], true);
|
| | | if (result) {
|
| | | results.push(result);
|
| | | if (this.errShowType === 'toast' || this.errShowType === 'modal') break;
|
| | | }
|
| | | }
|
| | | } else {
|
| | | newFormData = invalidFields
|
| | | }
|
| | | if (Array.isArray(results)) {
|
| | | if (results.length === 0) results = null;
|
| | | }
|
| | |
|
| | | if (Array.isArray(keepitem)) {
|
| | | keepitem.forEach(v => {
|
| | | newFormData[v] = this.dataValue[v];
|
| | | });
|
| | | }
|
| | |
|
| | | if (type === 'submit') {
|
| | | this.$emit('submit', {
|
| | | detail: {
|
| | | value: newFormData,
|
| | | errors: results
|
| | | }
|
| | | });
|
| | | } else {
|
| | | this.$emit('validate', results);
|
| | | }
|
| | |
|
| | | callback && typeof callback === 'function' && callback(results, newFormData);
|
| | |
|
| | | if (promise && callback) {
|
| | | return promise;
|
| | | } else {
|
| | | return null;
|
| | | }
|
| | | },
|
| | | submitForm() {},
|
| | | /**
|
| | | * 外部调用方法
|
| | | * 手动提交校验表单
|
| | | * 对整个表单进行校验的方法,参数为一个回调函数。
|
| | | */
|
| | | 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.validateAll(this.formData, 'submit', keepitem, callback);
|
| | | },
|
| | |
|
| | | /**
|
| | | * 外部调用方法
|
| | | * 校验表单
|
| | | * 对整个表单进行校验的方法,参数为一个回调函数。
|
| | | */
|
| | | validate(keepitem, callback) {
|
| | | return this.submit(keepitem, callback, true);
|
| | | },
|
| | |
|
| | | /**
|
| | | * 部分表单校验
|
| | | * @param {Object} props
|
| | | * @param {Object} cb
|
| | | */
|
| | | validateField(props, callback) {
|
| | | props = [].concat(props);
|
| | | let invalidFields = {};
|
| | | this.childrens.forEach(item => {
|
| | | if (props.indexOf(item.name) !== -1) {
|
| | | invalidFields = Object.assign({}, invalidFields, {
|
| | | [item.name]: this.formData[item.name]
|
| | | });
|
| | | }
|
| | | });
|
| | | return this.validateAll(invalidFields, 'submit', [], callback);
|
| | | },
|
| | |
|
| | | /**
|
| | | * 对整个表单进行重置,将所有字段值重置为初始值并移除校验结果
|
| | | */
|
| | | resetFields() {
|
| | | this.resetForm();
|
| | | },
|
| | |
|
| | | /**
|
| | | * 移除表单项的校验结果。传入待移除的表单项的 prop 属性或者 prop 组成的数组,如不传则移除整个表单的校验结果
|
| | | */
|
| | | clearValidate(props) {
|
| | | props = [].concat(props);
|
| | | this.childrens.forEach(item => {
|
| | | const inputComp = this.inputChildrens.find(child => child.rename === item.name);
|
| | | if (props.length === 0) {
|
| | | item.errMsg = '';
|
| | | if (inputComp) {
|
| | | inputComp.errMsg = '';
|
| | | }
|
| | | } else {
|
| | | if (props.indexOf(item.name) !== -1) {
|
| | | item.errMsg = '';
|
| | | if (inputComp) {
|
| | | inputComp.errMsg = '';
|
| | | }
|
| | | }
|
| | | }
|
| | | });
|
| | | },
|
| | | /**
|
| | | * 把 value 转换成指定的类型
|
| | | * @param {Object} key
|
| | | * @param {Object} value
|
| | | */
|
| | | _getValue(key, value) {
|
| | | const rules = (this.formRules[key] && this.formRules[key].rules) || [];
|
| | | const isRuleNum = rules.find(val => val.format && this.type_filter(val.format));
|
| | | const isRuleBool = rules.find(val => (val.format && val.format === 'boolean') || val.format === 'bool');
|
| | | // 输入值为 number
|
| | | if (isRuleNum) {
|
| | | value = isNaN(value) ? value : value === '' || value === null ? null : Number(value);
|
| | | }
|
| | | // 简单判断真假值
|
| | | if (isRuleBool) {
|
| | | value = !value ? false : true;
|
| | | }
|
| | | return value;
|
| | | },
|
| | | /**
|
| | | * 过滤数字类型
|
| | | * @param {Object} format
|
| | | */
|
| | | type_filter(format) {
|
| | | return format === 'int' || format === 'double' || format === 'number' || format === 'timestamp';
|
| | | }
|
| | | }
|
| | | };
|
| | | </script>
|
| | |
|
| | | <style lang="scss" >
|
| | | .uni-forms {
|
| | | // overflow: hidden;
|
| | | // padding: 10px 15px;
|
| | | }
|
| | |
|
| | | .uni-forms--top {
|
| | | // padding: 10px 15px;
|
| | | // padding-top: 22px;
|
| | | }
|
| | | </style>
|