| <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, invalidFields) { | 
|               valid ? resolve(valid) : reject(invalidFields); | 
|             }; | 
|           }); | 
|         } | 
|   | 
|         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> |