mirror of https://github.com/ElemeFE/element
Form: label-width supports width auto (#14944)
parent
e7fdd3dc50
commit
a408b3dd3f
|
@ -593,7 +593,7 @@ All components in a Form inherit their `size` attribute from that Form. Similarl
|
|||
| rules | validation rules of form | object | — | — |
|
||||
| inline | whether the form is inline | boolean | — | false |
|
||||
| label-position | position of label. If set to 'left' or 'right', `label-width` prop is also required | string | left / right / top | right |
|
||||
| label-width | width of label, and all its direct child form items will inherit this value | string | — | — |
|
||||
| label-width | width of label, e.g. '50px'. All its direct child form items will inherit this value. Width `auto` is supported. | string | — | — |
|
||||
| label-suffix | suffix of the label | string | — | — |
|
||||
| hide-required-asterisk | whether required fields should have a red asterisk (star) beside their labels | boolean | — | false |
|
||||
| show-message | whether to show the error message | boolean | — | true |
|
||||
|
@ -623,7 +623,7 @@ All components in a Form inherit their `size` attribute from that Form. Similarl
|
|||
| ---- | ----| ---- | ---- | ---- |
|
||||
| prop | a key of `model`. In the use of validate and resetFields method, the attribute is required | string | keys of model that passed to `form` |
|
||||
| label | label | string | — | — |
|
||||
| label-width | width of label, e.g. '50px' | string | — | — |
|
||||
| label-width | width of label, e.g. '50px'. Width `auto` is supported. | string | — | — |
|
||||
| required | whether the field is required or not, will be determined by validation rules if omitted | boolean | — | false |
|
||||
| rules | validation rules of form | object | — | — |
|
||||
| error | field error message, set its value and the field will validate error and show this message immediately | string | — | — |
|
||||
|
|
|
@ -607,7 +607,7 @@ Todos los componentes de un formulario heredan su atributo `size`. De manera sim
|
|||
| rules | Reglas de validación | object | — | — |
|
||||
| inline | Si el form es inline | boolean | — | false |
|
||||
| label-position | Posicion de la etiqueta | string | left / right / top | right |
|
||||
| label-width | ancho de la etiqueta, y todos los form items directos descendientes heredarán este valor | string | — | — |
|
||||
| label-width | width of label, e.g. '50px'. All its direct child form items will inherit this value. Width `auto` is supported. | string | — | — |
|
||||
| label-suffix | sufijo de la etiqueta | string | — | — |
|
||||
| hide-required-asterisk | si los campos obligatorios deben tener un asterisco rojo (estrella) al lado de sus etiquetas | boolean | — | false |
|
||||
| show-message | si mostrar o no el mensaje de error | boolean | — | true |
|
||||
|
@ -638,7 +638,7 @@ Todos los componentes de un formulario heredan su atributo `size`. De manera sim
|
|||
| -------------- | ------------------------------------------------------------ | ------- | ------------------------------------------- | ----------- |
|
||||
| prop | un clave del modelo. En el uso del método validate and resetFields, el atributo es obligatorio. | string | Clave del modelo que se ha pasado a `form` | |
|
||||
| label | etiqueta | string | — | — |
|
||||
| label-width | ancho de la etiqueta, e.g. '50px' | string | — | — |
|
||||
| label-width | ancho de la etiqueta, e.g. '50px'. Width `auto` is supported | string | — | — |
|
||||
| required | si el campo es obligatorio o no, estará determinado por las reglas de validación si se omite. | boolean | — | false |
|
||||
| rules | reglas de validacion del form | object | — | — |
|
||||
| error | mensaje de error de campo, establezca su valor y el campo validará el error y mostrará este mensaje inmediatamente. | string | — | — |
|
||||
|
|
|
@ -592,7 +592,7 @@ Tout les composants d'un formulaire héritent leur attribut `size` de ce formula
|
|||
| rules | Règles de validation du formulaire. | object | — | — |
|
||||
| inline | Si le formulaire est horizontal. | boolean | — | false |
|
||||
| label-position | Position des labels. Si 'left' ou 'right', `label-width` est aussi requis. | string | left / right / top | right |
|
||||
| label-width | Largeur des labels, tout les enfants directs hériteront de cette valeur. | string | — | — |
|
||||
| label-width | Largeur des labels, tout les enfants directs hériteront de cette valeur. Width `auto` is supported. | string | — | — |
|
||||
| label-suffix | Suffixe de labels. | string | — | — |
|
||||
| hide-required-asterisk | Si les champs obligatoires doivent avoir une astérisque rouge (étoile) à coté de leurs labels. | boolean | — | false |
|
||||
| show-message | Si le message d'erreur doit apparaître. | boolean | — | true |
|
||||
|
@ -623,7 +623,7 @@ Tout les composants d'un formulaire héritent leur attribut `size` de ce formula
|
|||
| ---- | ----| ---- | ---- | ---- |
|
||||
| prop | Une des clés de `model`. Utilisés par les méthodes validate et resetFields. Requis. | string | Clés du model passé à `form`. |
|
||||
| label | Le label. | string | — | — |
|
||||
| label-width | Largeur du label, e.g. '50px'. | string | — | — |
|
||||
| label-width | Largeur du label, e.g. '50px'. Width `auto` is supported. | string | — | — |
|
||||
| required | Si le champ est requis ou non. Si omis, sera déterminé par les règles de validation. | boolean | — | false |
|
||||
| rules | Règles de validation du formulaire. | object | — | — |
|
||||
| error | Message d'erreur du champ. Si il est modifié, le champ l'affichera immédiatement. | string | — | — |
|
||||
|
|
|
@ -588,7 +588,7 @@ W3C 标准中有如下[规定](https://www.w3.org/MarkUp/html-spec/html-spec_8.h
|
|||
| rules | 表单验证规则 | object | — | — |
|
||||
| inline | 行内表单模式 | boolean | — | false |
|
||||
| label-position | 表单域标签的位置,如果值为 left 或者 right 时,则需要设置 `label-width` | string | right/left/top | right |
|
||||
| label-width | 表单域标签的宽度,作为 Form 直接子元素的 form-item 会继承该值 | string | — | — |
|
||||
| label-width | 表单域标签的宽度,例如 '50px'。作为 Form 直接子元素的 form-item 会继承该值。支持 `auto`。 | string | — | — |
|
||||
| label-suffix | 表单域标签的后缀 | string | — | — |
|
||||
| hide-required-asterisk | 是否显示必填字段的标签旁边的红色星号 | boolean | — | false |
|
||||
| show-message | 是否显示校验错误信息 | boolean | — | true |
|
||||
|
@ -618,7 +618,7 @@ W3C 标准中有如下[规定](https://www.w3.org/MarkUp/html-spec/html-spec_8.h
|
|||
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
||||
| prop | 表单域 model 字段,在使用 validate、resetFields 方法的情况下,该属性是必填的 | string | 传入 Form 组件的 `model` 中的字段 | — |
|
||||
| label | 标签文本 | string | — | — |
|
||||
| label-width | 表单域标签的的宽度,例如 '50px' | string | — | — |
|
||||
| label-width | 表单域标签的的宽度,例如 '50px'。支持 `auto`。 | string | — | — |
|
||||
| required | 是否必填,如不设置,则会根据校验规则自动生成 | boolean | — | false |
|
||||
| rules | 表单验证规则 | object | — | — |
|
||||
| error | 表单域验证错误信息, 设置该值会使表单验证状态变为`error`,并显示该错误信息 | string | — | — |
|
||||
|
|
|
@ -9,9 +9,13 @@
|
|||
},
|
||||
sizeClass ? 'el-form-item--' + sizeClass : ''
|
||||
]">
|
||||
<label :for="labelFor" class="el-form-item__label" :style="labelStyle" v-if="label || $slots.label">
|
||||
<slot name="label">{{label + form.labelSuffix}}</slot>
|
||||
</label>
|
||||
<label-wrap
|
||||
:is-auto-width="labelStyle && labelStyle.width === 'auto'"
|
||||
:update-all="form.labelWidth === 'auto'">
|
||||
<label :for="labelFor" class="el-form-item__label" :style="labelStyle" v-if="label || $slots.label">
|
||||
<slot name="label">{{label + form.labelSuffix}}</slot>
|
||||
</label>
|
||||
</label-wrap>
|
||||
<div class="el-form-item__content" :style="contentStyle">
|
||||
<slot></slot>
|
||||
<transition name="el-zoom-in-top">
|
||||
|
@ -39,7 +43,7 @@
|
|||
import emitter from 'element-ui/src/mixins/emitter';
|
||||
import objectAssign from 'element-ui/src/utils/merge';
|
||||
import { noop, getPropByPath } from 'element-ui/src/utils/util';
|
||||
|
||||
import LabelWrap from './label-wrap';
|
||||
export default {
|
||||
name: 'ElFormItem',
|
||||
|
||||
|
@ -77,6 +81,10 @@
|
|||
},
|
||||
size: String
|
||||
},
|
||||
components: {
|
||||
// use this component to calculate auto width
|
||||
LabelWrap
|
||||
},
|
||||
watch: {
|
||||
error: {
|
||||
immediate: true,
|
||||
|
@ -108,7 +116,13 @@
|
|||
if (this.form.labelPosition === 'top' || this.form.inline) return ret;
|
||||
if (!label && !this.labelWidth && this.isNested) return ret;
|
||||
const labelWidth = this.labelWidth || this.form.labelWidth;
|
||||
if (labelWidth) {
|
||||
if (labelWidth === 'auto') {
|
||||
if (this.labelWidth === 'auto') {
|
||||
ret.marginLeft = this.computedLabelWidth;
|
||||
} else if (this.form.labelWidth === 'auto') {
|
||||
ret.marginLeft = this.elForm.autoLabelWidth;
|
||||
}
|
||||
} else {
|
||||
ret.marginLeft = labelWidth;
|
||||
}
|
||||
return ret;
|
||||
|
@ -167,7 +181,8 @@
|
|||
validateMessage: '',
|
||||
validateDisabled: false,
|
||||
validator: {},
|
||||
isNested: false
|
||||
isNested: false,
|
||||
computedLabelWidth: ''
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
|
@ -261,6 +276,9 @@
|
|||
}
|
||||
|
||||
this.validate('change');
|
||||
},
|
||||
updateComputedLabelWidth(width) {
|
||||
this.computedLabelWidth = width ? `${width}px` : '';
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
|
|
@ -54,9 +54,16 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
autoLabelWidth() {
|
||||
const max = Math.max(...this.potentialLabelWidthArr);
|
||||
return max ? `${max}px` : '';
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
fields: []
|
||||
fields: [],
|
||||
potentialLabelWidthArr: [] // use this array to calculate auto width
|
||||
};
|
||||
},
|
||||
created() {
|
||||
|
@ -142,6 +149,26 @@
|
|||
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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
<script>
|
||||
|
||||
export default {
|
||||
props: {
|
||||
isAutoWidth: Boolean,
|
||||
updateAll: Boolean
|
||||
},
|
||||
|
||||
inject: ['elForm', 'elFormItem'],
|
||||
|
||||
render() {
|
||||
const slots = this.$slots.default;
|
||||
if (!slots) return null;
|
||||
if (this.isAutoWidth) {
|
||||
return (<div class="el-form-item__label-wrap">
|
||||
{ slots }
|
||||
</div>);
|
||||
} else {
|
||||
return slots[0];
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
getLabelWidth() {
|
||||
if (this.$el && this.$el.firstElementChild) {
|
||||
const computedWidth = window.getComputedStyle(this.$el.firstElementChild).width;
|
||||
return Math.ceil(parseFloat(computedWidth));
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
updateLabelWidth(action = 'update') {
|
||||
if (this.$slots.default && this.isAutoWidth && this.$el.firstElementChild) {
|
||||
if (action === 'update') {
|
||||
this.computedWidth = this.getLabelWidth();
|
||||
} else if (action === 'remove') {
|
||||
this.elForm.deregisterLabelWidth(this.computedWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
computedWidth(val, oldVal) {
|
||||
if (this.updateAll) {
|
||||
this.elForm.registerLabelWidth(val, oldVal);
|
||||
this.elFormItem.updateComputedLabelWidth(val);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
computedWidth: 0
|
||||
};
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.updateLabelWidth('update');
|
||||
},
|
||||
|
||||
// Is this necessary?
|
||||
// updated() {
|
||||
// this.updateLabelWidth('update');
|
||||
// },
|
||||
|
||||
beforeDestroy() {
|
||||
this.updateLabelWidth('remove');
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -84,6 +84,14 @@
|
|||
}
|
||||
}
|
||||
|
||||
@include e(label-wrap) {
|
||||
float: left;
|
||||
.el-form-item__label {
|
||||
display: inline-block;
|
||||
float: none;
|
||||
}
|
||||
}
|
||||
|
||||
@include e(label) {
|
||||
text-align: right;
|
||||
vertical-align: middle;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { createVue, destroyVM } from '../util';
|
||||
import { createVue, destroyVM, waitImmediate } from '../util';
|
||||
|
||||
const DELAY = 50;
|
||||
|
||||
|
@ -43,6 +43,43 @@ describe('Form', () => {
|
|||
expect(vm.$el.querySelector('.el-form-item__content').style.marginLeft).to.equal('80px');
|
||||
done();
|
||||
});
|
||||
it('auto label width', async() => {
|
||||
vm = createVue({
|
||||
template: `
|
||||
<el-form ref="form" :model="form" label-width="auto">
|
||||
<el-form-item label="活动名称">
|
||||
<el-input v-model="form.name"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="活动备注信息" v-if="display">
|
||||
<el-input v-model="form.name"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
`,
|
||||
data() {
|
||||
return {
|
||||
display: true,
|
||||
form: {
|
||||
name: '',
|
||||
intro: ''
|
||||
}
|
||||
};
|
||||
}
|
||||
}, true);
|
||||
|
||||
await waitImmediate();
|
||||
|
||||
const formItems = vm.$el.querySelectorAll('.el-form-item__content');
|
||||
const marginLeft = parseInt(formItems[0].style.marginLeft, 10);
|
||||
const marginLeft1 = parseInt(formItems[1].style.marginLeft, 10);
|
||||
expect(marginLeft === marginLeft1).to.be.true;
|
||||
|
||||
vm.display = false;
|
||||
await waitImmediate();
|
||||
|
||||
const formItem = vm.$el.querySelector('.el-form-item__content');
|
||||
const newMarginLeft = parseInt(formItem.style.marginLeft, 10);
|
||||
expect(newMarginLeft < marginLeft).to.be.true;
|
||||
});
|
||||
it('inline form', done => {
|
||||
vm = createVue({
|
||||
template: `
|
||||
|
|
Loading…
Reference in New Issue