Input: add show-word-count attribute (#15075)

pull/15195/head
luckyCao 2019-04-19 16:14:07 +08:00 committed by hetech
parent da01541d60
commit 88ae222c61
8 changed files with 313 additions and 5 deletions

View File

@ -1,4 +1,4 @@
## Input ## Input
Input data using mouse or keyboard. Input data using mouse or keyboard.
@ -521,6 +521,42 @@ Search data from server-side.
``` ```
::: :::
### Limit length
:::demo `maxlength` and `minlength` are attributes of native input, they declare a limit on the number of characters a user can input. The "number of characters" is measured using JavaScript string length.Setting the `maxlength` prop for a text or textarea type of Input can limit the length of input value, allows you to show word count by setting `show-word-limit` to `true` at the same time.
```html
<el-input
type="text"
placeholder="Please input"
v-model="text"
maxlength="10"
show-word-limit
>
</el-input>
<div style="margin: 20px 0;"></div>
<el-input
type="textarea"
placeholder="Please input"
v-model="textarea"
maxlength="30"
show-word-limit
>
</el-input>
<script>
export default {
data() {
return {
text: '',
textarea: ''
}
}
}
</script>
```
:::
### Input Attributes ### Input Attributes
| Attribute | Description | Type | Accepted Values | Default | | Attribute | Description | Type | Accepted Values | Default |
@ -529,6 +565,7 @@ Search data from server-side.
|value / v-model| binding value | string / number| — | — | |value / v-model| binding value | string / number| — | — |
|maxlength| same as `maxlength` in native input | number| — | — | |maxlength| same as `maxlength` in native input | number| — | — |
|minlength| same as `minlength` in native input | number | — | — | |minlength| same as `minlength` in native input | number | — | — |
|show-word-limit | whether show word countonly works when `type` is 'text' or 'textarea' | boolean | — | false |
|placeholder| placeholder of Input| string | — | — | |placeholder| placeholder of Input| string | — | — |
| clearable | whether to show clear button | boolean | — | false | | clearable | whether to show clear button | boolean | — | false |
| show-password | whether to show toggleable password input| boolean | — | false | | show-password | whether to show toggleable password input| boolean | — | false |

View File

@ -285,7 +285,7 @@ export default {
<el-input <el-input
size="small" size="small"
placeholder="Please Input" placeholder="Please Input"
v-model="input2"> v-model="input3">
</el-input> </el-input>
<el-input <el-input
size="mini" size="mini"
@ -300,7 +300,7 @@ export default {
return { return {
input1: '', input1: '',
input2: '', input2: '',
input2: '', input3: '',
input4: '' input4: ''
} }
} }
@ -535,6 +535,42 @@ Búsqueda de datos desde el servidor.
::: :::
### Limit length
:::demo `maxlength` and `minlength` are attributes of native input, they declare a limit on the number of characters a user can input. The "number of characters" is measured using JavaScript string length.Setting the `maxlength` prop for a text or textarea type of Input can limit the length of input value, allows you to show word count by setting `show-word-limit` to `true` at the same time.
```html
<el-input
type="text"
placeholder="Please input"
v-model="text"
maxlength="10"
show-word-limit
>
</el-input>
<div style="margin: 20px 0;"></div>
<el-input
type="textarea"
placeholder="Please input"
v-model="textarea"
maxlength="30"
show-word-limit
>
</el-input>
<script>
export default {
data() {
return {
text: '',
textarea: ''
}
}
}
</script>
```
:::
### Input atributos ### Input atributos
| Atributo | Descripción | Tipo | Valores aceptados | Por defecto | | Atributo | Descripción | Tipo | Valores aceptados | Por defecto |
@ -543,6 +579,7 @@ Búsqueda de datos desde el servidor.
| value / v-model | valor enlazado | boolean / string / number | — | — | | value / v-model | valor enlazado | boolean / string / number | — | — |
| maxlength | igual que `maxlength` en el input nativo | number | — | — | | maxlength | igual que `maxlength` en el input nativo | number | — | — |
| minlength | igual que `minlength` en el input nativo | number | — | — | | minlength | igual que `minlength` en el input nativo | number | — | — |
| show-word-limit | whether show word countonly works when `type` is 'text' or 'textarea' | boolean | — | false |
| placeholder | placeholder del Input | string | — | — | | placeholder | placeholder del Input | string | — | — |
| clearable | si debe mostrar el boton de limpieza | boolean | — | false | | clearable | si debe mostrar el boton de limpieza | boolean | — | false |
| show-password | si debe mostrar la posibilidad de conmutacion de password input | boolean | — | false | | show-password | si debe mostrar la posibilidad de conmutacion de password input | boolean | — | false |

View File

@ -520,6 +520,42 @@ Vous pouvez aller chercher des infos de suggestions sur un serveur distant.
``` ```
::: :::
### Limit length
:::demo `maxlength` and `minlength` are attributes of native input, they declare a limit on the number of characters a user can input. The "number of characters" is measured using JavaScript string length.Setting the `maxlength` prop for a text or textarea type of Input can limit the length of input value, allows you to show word count by setting `show-word-limit` to `true` at the same time.
```html
<el-input
type="text"
placeholder="Please input"
v-model="text"
maxlength="10"
show-word-limit
>
</el-input>
<div style="margin: 20px 0;"></div>
<el-input
type="textarea"
placeholder="Please input"
v-model="textarea"
maxlength="30"
show-word-limit
>
</el-input>
<script>
export default {
data() {
return {
text: '',
textarea: ''
}
}
}
</script>
```
:::
### Attributs de l'Input ### Attributs de l'Input
| Attribut | Description | Type | Valeurs acceptées | Défaut | | Attribut | Description | Type | Valeurs acceptées | Défaut |
@ -528,6 +564,7 @@ Vous pouvez aller chercher des infos de suggestions sur un serveur distant.
| value / v-model | Variable liée. | string / number | — | — | | value / v-model | Variable liée. | string / number | — | — |
| maxlength| Identique à `maxlength` dans l'input natif. | number| — | — | | maxlength| Identique à `maxlength` dans l'input natif. | number| — | — |
| minlength| Identique à `minlength` dans l'input natif. | number | — | — | | minlength| Identique à `minlength` dans l'input natif. | number | — | — |
| show-word-limit | whether show word countonly works when `type` is 'text' or 'textarea' | boolean | — | false |
| placeholder| Placeholder de l' Input. | string | — | — | | placeholder| Placeholder de l' Input. | string | — | — |
| clearable | Si le bouton de reset apparaît. | boolean | — | false | | clearable | Si le bouton de reset apparaît. | boolean | — | false |
| show-password | Si le champ doit un champ de mot de passe avec bouton de visualisation. | boolean | — | false | | show-password | Si le champ doit un champ de mot de passe avec bouton de visualisation. | boolean | — | false |

View File

@ -639,6 +639,41 @@ export default {
``` ```
::: :::
### 输入长度限制
:::demo `maxlength``minlength` 是原生属性,用来限制输入框的字符长度,其中字符长度是用 Javascript 的字符串长度统计的。对于类型为 `text``textarea` 的输入框,在使用 `maxlength` 属性限制最大输入长度的同时,可通过设置 `show-word-limit` 属性来展示字数统计。
```html
<el-input
type="text"
placeholder="请输入内容"
v-model="text"
maxlength="10"
show-word-limit
>
</el-input>
<div style="margin: 20px 0;"></div>
<el-input
type="textarea"
placeholder="请输入内容"
v-model="textarea"
maxlength="30"
show-word-limit
>
</el-input>
<script>
export default {
data() {
return {
text: '',
textarea: ''
}
}
}
</script>
```
:::
### Input Attributes ### Input Attributes
| 参数 | 说明 | 类型 | 可选值 | 默认值 | | 参数 | 说明 | 类型 | 可选值 | 默认值 |
@ -647,6 +682,7 @@ export default {
| value / v-model | 绑定值 | string / number | — | — | | value / v-model | 绑定值 | string / number | — | — |
| maxlength | 原生属性,最大输入长度 | number | — | — | | maxlength | 原生属性,最大输入长度 | number | — | — |
| minlength | 原生属性,最小输入长度 | number | — | — | | minlength | 原生属性,最小输入长度 | number | — | — |
| show-word-limit | 是否显示输入字数统计,只在 `type = "text"``type = "textarea"` 时有效 | boolean | — | false |
| placeholder | 输入框占位文本 | string | — | — | | placeholder | 输入框占位文本 | string | — | — |
| clearable | 是否可清空 | boolean | — | false | | clearable | 是否可清空 | boolean | — | false |
| show-password | 是否显示切换密码图标| boolean | — | false | | show-password | 是否显示切换密码图标| boolean | — | false |

View File

@ -4,6 +4,7 @@
inputSize ? 'el-input--' + inputSize : '', inputSize ? 'el-input--' + inputSize : '',
{ {
'is-disabled': inputDisabled, 'is-disabled': inputDisabled,
'is-exceed': inputExceed,
'el-input-group': $slots.prepend || $slots.append, 'el-input-group': $slots.prepend || $slots.append,
'el-input-group--append': $slots.append, 'el-input-group--append': $slots.append,
'el-input-group--prepend': $slots.prepend, 'el-input-group--prepend': $slots.prepend,
@ -48,9 +49,9 @@
<!-- 后置内容 --> <!-- 后置内容 -->
<span <span
class="el-input__suffix" class="el-input__suffix"
v-if="$slots.suffix || suffixIcon || showClear || showPassword || validateState && needStatusIcon"> v-if="getSuffixVisible()">
<span class="el-input__suffix-inner"> <span class="el-input__suffix-inner">
<template v-if="!showClear || !showPwdVisible"> <template v-if="!showClear || !showPwdVisible || !isWordLimitVisible">
<slot name="suffix"></slot> <slot name="suffix"></slot>
<i class="el-input__icon" <i class="el-input__icon"
v-if="suffixIcon" v-if="suffixIcon"
@ -65,6 +66,11 @@
class="el-input__icon el-icon-view el-input__clear" class="el-input__icon el-icon-view el-input__clear"
@click="handlePasswordVisible" @click="handlePasswordVisible"
></i> ></i>
<span v-if="isWordLimitVisible" class="el-input__count">
<span class="el-input__count-inner">
{{ textLength }}/{{ upperLimit }}
</span>
</span>
</span> </span>
<i class="el-input__icon" <i class="el-input__icon"
v-if="validateState" v-if="validateState"
@ -95,6 +101,7 @@
:aria-label="label" :aria-label="label"
> >
</textarea> </textarea>
<span v-if="isWordLimitVisible && type === 'textarea'" class="el-input__count">{{ textLength }}/{{ upperLimit }}</span>
</div> </div>
</template> </template>
<script> <script>
@ -174,6 +181,10 @@
type: Boolean, type: Boolean,
default: false default: false
}, },
showWordLimit: {
type: Boolean,
default: false
},
tabindex: String tabindex: String
}, },
@ -218,6 +229,29 @@
!this.inputDisabled && !this.inputDisabled &&
!this.readonly && !this.readonly &&
(!!this.nativeInputValue || this.focused); (!!this.nativeInputValue || this.focused);
},
isWordLimitVisible() {
return this.showWordLimit &&
this.$attrs.maxlength &&
(this.type === 'text' || this.type === 'textarea') &&
!this.inputDisabled &&
!this.readonly &&
!this.showPassword;
},
upperLimit() {
return this.$attrs.maxlength;
},
textLength() {
if (typeof this.value === 'number') {
return String(this.value).length;
}
return (this.value || '').length;
},
inputExceed() {
// show exceed style if length of initial value greater then maxlength
return this.isWordLimitVisible &&
(this.textLength > this.upperLimit);
} }
}, },
@ -362,6 +396,14 @@
}, },
getInput() { getInput() {
return this.$refs.input || this.$refs.textarea; return this.$refs.input || this.$refs.textarea;
},
getSuffixVisible() {
return this.$slots.suffix ||
this.suffixIcon ||
this.showClear ||
this.showPassword ||
this.isWordLimitVisible ||
(this.validateState && this.needStatusIcon);
} }
}, },

View File

@ -2,6 +2,7 @@
@import "common/var"; @import "common/var";
@include b(textarea) { @include b(textarea) {
position: relative;
display: inline-block; display: inline-block;
width: 100%; width: 100%;
vertical-align: bottom; vertical-align: bottom;
@ -36,6 +37,15 @@
} }
} }
& .el-input__count {
color: $--color-info;
background: $--color-white;
position: absolute;
font-size: 12px;
bottom: 5px;
right: 10px;
}
@include when(disabled) { @include when(disabled) {
.el-textarea__inner { .el-textarea__inner {
background-color: $--input-disabled-fill; background-color: $--input-disabled-fill;
@ -48,6 +58,16 @@
} }
} }
} }
@include when(exceed) {
.el-textarea__inner {
border-color: $--color-danger;
}
.el-input__count {
color: $--color-danger;
}
}
} }
@include b(input) { @include b(input) {
@ -69,6 +89,20 @@
} }
} }
& .el-input__count {
height: 100%;
display: inline-flex;
align-items: center;
color: $--color-info;
font-size: 12px;
.el-input__count-inner {
background: $--color-white;
display: inline-block;
padding: 0 5px;
}
}
@include e(inner) { @include e(inner) {
-webkit-appearance: none; -webkit-appearance: none;
background-color: $--input-background-color; background-color: $--input-background-color;
@ -169,6 +203,18 @@
} }
} }
@include when(exceed) {
.el-input__inner {
border-color: $--color-danger;
}
.el-input__suffix {
.el-input__count {
color: $--color-danger;
}
}
}
@include m(suffix) { @include m(suffix) {
.el-input__inner { .el-input__inner {
padding-right: 30px; padding-right: 30px;

View File

@ -416,4 +416,68 @@ describe('Input', () => {
await waitImmediate(); await waitImmediate();
expect(vm.$el.querySelector('input').value).to.equal('123'); expect(vm.$el.querySelector('input').value).to.equal('123');
}); });
it('limit input and show word count', async() => {
vm = createVue({
template: `
<div>
<el-input
class="test-text"
type="text"
v-model="input1"
maxlength="10"
:show-word-limit="show">
</el-input>
<el-input
class="test-textarea"
type="textarea"
v-model="input2"
maxlength="10"
show-word-limit>
</el-input>
<el-input
class="test-password"
type="password"
v-model="input3"
maxlength="10"
show-word-limit>
</el-input>
<el-input
class="test-initial-exceed"
type="text"
v-model="input4"
maxlength="2"
show-word-limit>
</el-input>
</div>
`,
data() {
return {
input1: '',
input2: '',
input3: '',
input4: 'exceed',
show: false
};
}
}, true);
const inputElm1 = vm.$el.querySelector('.test-text');
const inputElm2 = vm.$el.querySelector('.test-textarea');
const inputElm3 = vm.$el.querySelector('.test-password');
const inputElm4 = vm.$el.querySelector('.test-initial-exceed');
expect(inputElm1.querySelectorAll('.el-input__count').length).to.equal(0);
expect(inputElm2.querySelectorAll('.el-input__count').length).to.equal(1);
expect(inputElm3.querySelectorAll('.el-input__count').length).to.equal(0);
expect(inputElm4.classList.contains('is-exceed')).to.true;
vm.show = true;
await waitImmediate();
expect(inputElm1.querySelectorAll('.el-input__count').length).to.equal(1);
vm.input4 = '1';
await waitImmediate();
expect(inputElm4.classList.contains('is-exceed')).to.false;
});
}); });

9
types/input.d.ts vendored
View File

@ -81,6 +81,15 @@ export declare class ElInput extends ElementUIComponent {
/** Whether to trigger form validatio */ /** Whether to trigger form validatio */
validateEvent: boolean validateEvent: boolean
/** Whether the input is clearable */
clearable: boolean
/** Whether to show password */
showPassword: boolean
/** Whether to show wordCount when setting maxLength */
showWordLimit: boolean
/** /**
* Focus the Input component * Focus the Input component
*/ */