You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

183 lines
4.8 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<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>