<template> <form class="el-form" :class="[ labelPosition ? 'el-form--label-' + labelPosition : '', { 'el-form--inline': inline } ]"> <slot></slot> </form> </template> <script> import objectAssign from 'element-ui/src/utils/merge'; export default { name: 'ElForm', componentName: 'ElForm', provide() { return { elForm: this }; }, props: { model: Object, rules: Object, labelPosition: String, labelWidth: String, labelSuffix: { type: String, default: '' }, inline: Boolean, inlineMessage: Boolean, statusIcon: Boolean, showMessage: { type: Boolean, default: true }, size: String, disabled: Boolean, validateOnRuleChange: { type: Boolean, default: true }, hideRequiredAsterisk: { type: Boolean, default: false } }, watch: { rules() { // remove then add event listeners on form-item after form rules change this.fields.forEach(field => { field.removeValidateEvents(); field.addValidateEvents(); }); if (this.validateOnRuleChange) { this.validate(() => {}); } } }, computed: { autoLabelWidth() { if (!this.potentialLabelWidthArr.length) return 0; const max = Math.max(...this.potentialLabelWidthArr); return max ? `${max}px` : ''; } }, data() { return { fields: [], potentialLabelWidthArr: [] // use this array to calculate auto width }; }, created() { this.$on('el.form.addField', (field) => { if (field) { this.fields.push(field); } }); /* istanbul ignore next */ this.$on('el.form.removeField', (field) => { if (field.prop) { this.fields.splice(this.fields.indexOf(field), 1); } }); }, methods: { resetFields() { if (!this.model) { console.warn('[Element Warn][Form]model is required for resetFields to work.'); return; } this.fields.forEach(field => { field.resetField(); }); }, clearValidate(props = []) { const fields = props.length ? (typeof props === 'string' ? this.fields.filter(field => props === field.prop) : this.fields.filter(field => props.indexOf(field.prop) > -1) ) : this.fields; fields.forEach(field => { field.clearValidate(); }); }, validate(callback) { if (!this.model) { console.warn('[Element Warn][Form]model is required for validate to work!'); return; } let promise; // if no callback, return promise if (typeof callback !== 'function' && window.Promise) { promise = new window.Promise((resolve, reject) => { callback = function(valid) { valid ? resolve(valid) : reject(valid); }; }); } let valid = true; let count = 0; // 如果需要验证的fields为空,调用验证时立刻返回callback if (this.fields.length === 0 && callback) { callback(true); } let invalidFields = {}; this.fields.forEach(field => { field.validate('', (message, field) => { if (message) { valid = false; } invalidFields = objectAssign({}, invalidFields, field); if (typeof callback === 'function' && ++count === this.fields.length) { callback(valid, invalidFields); } }); }); if (promise) { return promise; } }, validateField(props, cb) { props = [].concat(props); const fields = this.fields.filter(field => props.indexOf(field.prop) !== -1); if (!fields.length) { console.warn('[Element Warn]please pass correct props!'); return; } fields.forEach(field => { field.validate('', cb); }); }, getLabelWidthIndex(width) { const index = this.potentialLabelWidthArr.indexOf(width); // it's impossible if (index === -1) { throw new Error('[ElementForm]unpected width ', width); } return index; }, registerLabelWidth(val, oldVal) { if (val && oldVal) { const index = this.getLabelWidthIndex(oldVal); this.potentialLabelWidthArr.splice(index, 1, val); } else if (val) { this.potentialLabelWidthArr.push(val); } }, deregisterLabelWidth(val) { const index = this.getLabelWidthIndex(val); this.potentialLabelWidthArr.splice(index, 1); } } }; </script>