add rows and autosize property

pull/225/head
baiyaaaaa 2016-10-04 12:17:19 +08:00
parent 3c10d063e8
commit 70410a2b1f
5 changed files with 157 additions and 19 deletions

View File

@ -8,6 +8,7 @@
- 修复 TimePicker 错误的隐藏面板
- 修复 Table Cell 的样式, #204
- 为 Message Box 和 Dialog 添加 lockScroll 属性,用于定义是否在弹框出现时将 body 滚动锁定
- 新增 Input textarea 类型的 rows, autosize 属性
### 1.0.0-rc.5

View File

@ -240,6 +240,8 @@
```html
<el-input
type="textarea"
placeholder="请输入内容"
:autosize="{minRows: 2, maxRows: 5}"
v-model="textarea">
</el-input>
```
@ -625,15 +627,17 @@
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|------------- |---------------- |---------------- |---------------------- |-------- |
| type | 同原生的 input 的 type 属性,如果为 textarea 则显示为 textarea | string | — | — |
| type | 同原生的 input 的 type 属性,另外提供 type="textarea" | string | — | — |
| value | 绑定值 | string, number | — | — |
| maxlength | 最大输入长度 | number | — | — |
| minlength | 最小输入长度 | number | — | — |
| placeholder | 输入框占位文本 | string | — | — |
| disabled | 禁用 | boolean | — | false |
| size | 输入框尺寸 | string | large, small, mini | — |
| size | 输入框尺寸,只在 `type!="textarea"` 时有效 | string | large, small, mini | — |
| 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

View File

@ -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'};
};

View File

@ -13,20 +13,20 @@
<slot name="prepend"></slot>
</div>
<input
class="el-input__inner"
v-model="currentValue"
:type="type"
:name="name"
class="el-input__inner"
:placeholder="placeholder"
v-model="currentValue"
:disabled="disabled"
:readonly="readonly"
@focus="$emit('onfocus', currentValue)"
@blur="handleBlur"
:number="number"
:maxlength="maxlength"
:minlength="minlength"
:autocomplete="autoComplete"
ref="input"
@focus="$emit('onfocus', currentValue)"
@blur="handleBlur"
>
<!-- input 图标 -->
<i class="el-input__icon" :class="[icon ? 'el-icon-' + icon : '']" v-if="icon"></i>
@ -36,12 +36,27 @@
<slot name="append"></slot>
</div>
</template>
<!-- 写成垂直的方式会导致 placeholder 失效, 蜜汁bug -->
<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>
<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>
</template>
<script>
import emitter from 'main/mixins/emitter';
import calcTextareaHeight from './calcTextareaHeight';
export default {
name: 'ElInput',
@ -82,6 +97,14 @@
type: Boolean,
default: false
},
autosize: {
type: [Boolean, Object],
default: false
},
rows: {
type: Number,
default: 2
},
autoComplete: {
type: String,
default: 'off'
@ -98,12 +121,22 @@
inputSelect() {
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() {
return {
currentValue: ''
currentValue: this.value,
textareaStyle: {}
};
},
@ -111,6 +144,10 @@
this.$on('inputSelect', this.inputSelect);
},
mounted() {
this.resizeTextarea();
},
computed: {
validating() {
return this.$parent.validating;
@ -118,16 +155,13 @@
},
watch: {
'value': {
immediate: true,
handler(val) {
this.currentValue = val;
}
'value'(val, oldValue) {
this.currentValue = val;
this.resizeTextarea();
},
'currentValue'(val) {
this.$emit('input', val);
this.$emit('onchange', val);
this.dispatch('form-item', 'el.form.change', [val]);
}
}

View File

@ -161,11 +161,10 @@
@e inner {
display: block;
resize: vertical;
padding: 8px 5px;
line-height: normal;
padding: 5px 7px;
line-height: 1.5;
box-sizing: border-box;
width: 100%;
min-height: 88px;
font-size: var(--font-size-base);
color: var(--input-color);
background-color: #fff;