mirror of https://github.com/ElemeFE/element
add rows and autosize property
parent
3c10d063e8
commit
70410a2b1f
|
@ -8,6 +8,7 @@
|
||||||
- 修复 TimePicker 错误的隐藏面板
|
- 修复 TimePicker 错误的隐藏面板
|
||||||
- 修复 Table Cell 的样式, #204
|
- 修复 Table Cell 的样式, #204
|
||||||
- 为 Message Box 和 Dialog 添加 lockScroll 属性,用于定义是否在弹框出现时将 body 滚动锁定
|
- 为 Message Box 和 Dialog 添加 lockScroll 属性,用于定义是否在弹框出现时将 body 滚动锁定
|
||||||
|
- 新增 Input textarea 类型的 rows, autosize 属性
|
||||||
|
|
||||||
### 1.0.0-rc.5
|
### 1.0.0-rc.5
|
||||||
|
|
||||||
|
|
|
@ -240,6 +240,8 @@
|
||||||
```html
|
```html
|
||||||
<el-input
|
<el-input
|
||||||
type="textarea"
|
type="textarea"
|
||||||
|
placeholder="请输入内容"
|
||||||
|
:autosize="{minRows: 2, maxRows: 5}"
|
||||||
v-model="textarea">
|
v-model="textarea">
|
||||||
</el-input>
|
</el-input>
|
||||||
```
|
```
|
||||||
|
@ -625,15 +627,17 @@
|
||||||
|
|
||||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||||
|------------- |---------------- |---------------- |---------------------- |-------- |
|
|------------- |---------------- |---------------- |---------------------- |-------- |
|
||||||
| type | 同原生的 input 的 type 属性,如果为 textarea 则显示为 textarea | string | — | — |
|
| type | 同原生的 input 的 type 属性,另外提供 type="textarea" | string | — | — |
|
||||||
| value | 绑定值 | string, number | — | — |
|
| value | 绑定值 | string, number | — | — |
|
||||||
| maxlength | 最大输入长度 | number | — | — |
|
| maxlength | 最大输入长度 | number | — | — |
|
||||||
| minlength | 最小输入长度 | number | — | — |
|
| minlength | 最小输入长度 | number | — | — |
|
||||||
| placeholder | 输入框占位文本 | string | — | — |
|
| placeholder | 输入框占位文本 | string | — | — |
|
||||||
| disabled | 禁用 | boolean | — | false |
|
| disabled | 禁用 | boolean | — | false |
|
||||||
| size | 输入框尺寸 | string | large, small, mini | — |
|
| size | 输入框尺寸,只在 `type!="textarea"` 时有效 | string | large, small, mini | — |
|
||||||
| icon | 输入框尾部图标 | string | — | — |
|
| icon | 输入框尾部图标 | string | — | — |
|
||||||
| number | 指定model值为number类型 | boolean | — | false |
|
| number | 指定 model 值为 number 类型 | boolean | — | false |
|
||||||
|
| rows | 输入框行数,只对 `type="textarea"` 有效 | number | — | 2 |
|
||||||
|
| autosize | 自适应内容高度,只对 `type="textarea"` 有效,可传入对象,如,{ minRows: 2, maxRows: 6 } | boolean/object | — | false |
|
||||||
|
|
||||||
### Autocomplete API
|
### Autocomplete API
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
let hiddenTextarea;
|
||||||
|
|
||||||
|
const HIDDEN_STYLE = `
|
||||||
|
height:0 !important;
|
||||||
|
visibility:hidden !important;
|
||||||
|
overflow:hidden !important;
|
||||||
|
position:absolute !important;
|
||||||
|
z-index:-1000 !important;
|
||||||
|
top:0 !important;
|
||||||
|
right:0 !important
|
||||||
|
`;
|
||||||
|
|
||||||
|
const CONTEXT_STYLE = [
|
||||||
|
'letter-spacing',
|
||||||
|
'line-height',
|
||||||
|
'padding-top',
|
||||||
|
'padding-bottom',
|
||||||
|
'font-family',
|
||||||
|
'font-weight',
|
||||||
|
'font-size',
|
||||||
|
'text-rendering',
|
||||||
|
'text-transform',
|
||||||
|
'width',
|
||||||
|
'text-indent',
|
||||||
|
'padding-left',
|
||||||
|
'padding-right',
|
||||||
|
'border-width',
|
||||||
|
'box-sizing'
|
||||||
|
];
|
||||||
|
|
||||||
|
function calculateNodeStyling(node) {
|
||||||
|
const style = window.getComputedStyle(node);
|
||||||
|
|
||||||
|
const boxSizing = style.getPropertyValue('box-sizing');
|
||||||
|
|
||||||
|
const paddingSize = (
|
||||||
|
parseFloat(style.getPropertyValue('padding-bottom')) +
|
||||||
|
parseFloat(style.getPropertyValue('padding-top'))
|
||||||
|
);
|
||||||
|
|
||||||
|
const borderSize = (
|
||||||
|
parseFloat(style.getPropertyValue('border-bottom-width')) +
|
||||||
|
parseFloat(style.getPropertyValue('border-top-width'))
|
||||||
|
);
|
||||||
|
|
||||||
|
const contextStyle = CONTEXT_STYLE
|
||||||
|
.map(name => `${name}:${style.getPropertyValue(name)}`)
|
||||||
|
.join(';');
|
||||||
|
|
||||||
|
return { contextStyle, paddingSize, borderSize, boxSizing };
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function calcTextareaHeight(
|
||||||
|
targetNode,
|
||||||
|
minRows = null,
|
||||||
|
maxRows = null
|
||||||
|
) {
|
||||||
|
if (!hiddenTextarea) {
|
||||||
|
hiddenTextarea = document.createElement('textarea');
|
||||||
|
document.body.appendChild(hiddenTextarea);
|
||||||
|
}
|
||||||
|
|
||||||
|
let {
|
||||||
|
paddingSize,
|
||||||
|
borderSize,
|
||||||
|
boxSizing,
|
||||||
|
contextStyle
|
||||||
|
} = calculateNodeStyling(targetNode);
|
||||||
|
|
||||||
|
hiddenTextarea.setAttribute('style', `${contextStyle};${HIDDEN_STYLE}`);
|
||||||
|
hiddenTextarea.value = targetNode.value || targetNode.placeholder || '';
|
||||||
|
|
||||||
|
let height = hiddenTextarea.scrollHeight;
|
||||||
|
|
||||||
|
if (boxSizing === 'border-box') {
|
||||||
|
height = height + borderSize;
|
||||||
|
} else if (boxSizing === 'content-box') {
|
||||||
|
height = height - paddingSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
hiddenTextarea.value = '';
|
||||||
|
let singleRowHeight = hiddenTextarea.scrollHeight - paddingSize;
|
||||||
|
|
||||||
|
if (minRows !== null) {
|
||||||
|
let minHeight = singleRowHeight * minRows;
|
||||||
|
if (boxSizing === 'border-box') {
|
||||||
|
minHeight = minHeight + paddingSize + borderSize;
|
||||||
|
}
|
||||||
|
height = Math.max(minHeight, height);
|
||||||
|
}
|
||||||
|
if (maxRows !== null) {
|
||||||
|
let maxHeight = singleRowHeight * maxRows;
|
||||||
|
if (boxSizing === 'border-box') {
|
||||||
|
maxHeight = maxHeight + paddingSize + borderSize;
|
||||||
|
}
|
||||||
|
height = Math.min(maxHeight, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { height: height + 'px'};
|
||||||
|
};
|
|
@ -13,20 +13,20 @@
|
||||||
<slot name="prepend"></slot>
|
<slot name="prepend"></slot>
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input
|
||||||
|
class="el-input__inner"
|
||||||
|
v-model="currentValue"
|
||||||
:type="type"
|
:type="type"
|
||||||
:name="name"
|
:name="name"
|
||||||
class="el-input__inner"
|
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
v-model="currentValue"
|
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:readonly="readonly"
|
:readonly="readonly"
|
||||||
@focus="$emit('onfocus', currentValue)"
|
|
||||||
@blur="handleBlur"
|
|
||||||
:number="number"
|
:number="number"
|
||||||
:maxlength="maxlength"
|
:maxlength="maxlength"
|
||||||
:minlength="minlength"
|
:minlength="minlength"
|
||||||
:autocomplete="autoComplete"
|
:autocomplete="autoComplete"
|
||||||
ref="input"
|
ref="input"
|
||||||
|
@focus="$emit('onfocus', currentValue)"
|
||||||
|
@blur="handleBlur"
|
||||||
>
|
>
|
||||||
<!-- input 图标 -->
|
<!-- input 图标 -->
|
||||||
<i class="el-input__icon" :class="[icon ? 'el-icon-' + icon : '']" v-if="icon"></i>
|
<i class="el-input__icon" :class="[icon ? 'el-icon-' + icon : '']" v-if="icon"></i>
|
||||||
|
@ -36,12 +36,27 @@
|
||||||
<slot name="append"></slot>
|
<slot name="append"></slot>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<!-- 写成垂直的方式会导致 placeholder 失效, 蜜汁bug -->
|
<textarea
|
||||||
<textarea v-else v-model="currentValue" class="el-textarea__inner" :name="name" :placeholder="placeholder" :disabled="disabled" :readonly="readonly" @focus="$emit('onfocus', currentValue)" @blur="handleBlur"></textarea>
|
v-else
|
||||||
|
class="el-textarea__inner"
|
||||||
|
v-model="currentValue"
|
||||||
|
ref="textarea"
|
||||||
|
:name="name"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
:disabled="disabled"
|
||||||
|
:style="textareaStyle"
|
||||||
|
:readonly="readonly"
|
||||||
|
:rows="rows"
|
||||||
|
:maxlength="maxlength"
|
||||||
|
:minlength="minlength"
|
||||||
|
@focus="$emit('onfocus', currentValue)"
|
||||||
|
@blur="handleBlur">
|
||||||
|
</textarea>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import emitter from 'main/mixins/emitter';
|
import emitter from 'main/mixins/emitter';
|
||||||
|
import calcTextareaHeight from './calcTextareaHeight';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ElInput',
|
name: 'ElInput',
|
||||||
|
@ -82,6 +97,14 @@
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
|
autosize: {
|
||||||
|
type: [Boolean, Object],
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
rows: {
|
||||||
|
type: Number,
|
||||||
|
default: 2
|
||||||
|
},
|
||||||
autoComplete: {
|
autoComplete: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'off'
|
default: 'off'
|
||||||
|
@ -98,12 +121,22 @@
|
||||||
|
|
||||||
inputSelect() {
|
inputSelect() {
|
||||||
this.$refs.input.select();
|
this.$refs.input.select();
|
||||||
|
},
|
||||||
|
resizeTextarea() {
|
||||||
|
var { autosize, type } = this;
|
||||||
|
if (!autosize || type !== 'textarea') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const minRows = autosize ? autosize.minRows : null;
|
||||||
|
const maxRows = autosize ? autosize.maxRows : null;
|
||||||
|
this.textareaStyle = calcTextareaHeight(this.$refs.textarea, minRows, maxRows);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
currentValue: ''
|
currentValue: this.value,
|
||||||
|
textareaStyle: {}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -111,6 +144,10 @@
|
||||||
this.$on('inputSelect', this.inputSelect);
|
this.$on('inputSelect', this.inputSelect);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.resizeTextarea();
|
||||||
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
validating() {
|
validating() {
|
||||||
return this.$parent.validating;
|
return this.$parent.validating;
|
||||||
|
@ -118,16 +155,13 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
'value': {
|
'value'(val, oldValue) {
|
||||||
immediate: true,
|
this.currentValue = val;
|
||||||
handler(val) {
|
this.resizeTextarea();
|
||||||
this.currentValue = val;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
'currentValue'(val) {
|
'currentValue'(val) {
|
||||||
this.$emit('input', val);
|
this.$emit('input', val);
|
||||||
this.$emit('onchange', val);
|
|
||||||
this.dispatch('form-item', 'el.form.change', [val]);
|
this.dispatch('form-item', 'el.form.change', [val]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,11 +161,10 @@
|
||||||
@e inner {
|
@e inner {
|
||||||
display: block;
|
display: block;
|
||||||
resize: vertical;
|
resize: vertical;
|
||||||
padding: 8px 5px;
|
padding: 5px 7px;
|
||||||
line-height: normal;
|
line-height: 1.5;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 88px;
|
|
||||||
font-size: var(--font-size-base);
|
font-size: var(--font-size-base);
|
||||||
color: var(--input-color);
|
color: var(--input-color);
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
|
Loading…
Reference in New Issue