198 lines
4.0 KiB
Vue
198 lines
4.0 KiB
Vue
<template>
|
|
<md-field-item
|
|
class="md-textarea-item"
|
|
:class="[
|
|
isDisabled ? 'is-disabled' : '',
|
|
errorInfo ? 'is-error' : ''
|
|
]"
|
|
:title="title"
|
|
:solid="solid"
|
|
>
|
|
<textarea
|
|
class="md-textarea-item__textarea"
|
|
ref="textarea"
|
|
v-model="inputValue"
|
|
:disabled="isDisabled"
|
|
:readonly="readonly"
|
|
:maxlength="maxLength"
|
|
:placeholder="placeholder"
|
|
:rows="rows"
|
|
@input="$_onInput"
|
|
@focus="$_onFocus"
|
|
@blur="$_onBlur"
|
|
@keyup="$_onKeyup"
|
|
@keydown="$_onKeydown"
|
|
></textarea>
|
|
<slot name="footer"></slot>
|
|
<template slot="children">
|
|
<div v-if="errorInfo" class="md-textarea-item-msg">
|
|
<p>{{ errorInfo }}</p>
|
|
</div>
|
|
</template>
|
|
</md-field-item>
|
|
</template>
|
|
<script>
|
|
import FieldItem from '../field-item'
|
|
|
|
export default {
|
|
name: 'md-textarea-item',
|
|
components: {
|
|
[FieldItem.name]: FieldItem,
|
|
},
|
|
props: {
|
|
title: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
placeholder: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
value: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
maxLength: {
|
|
type: [String, Number],
|
|
default: '',
|
|
},
|
|
maxHeight: {
|
|
type: [String, Number],
|
|
default: '',
|
|
},
|
|
solid: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
readonly: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
disabled: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
rows: {
|
|
type: [String, Number],
|
|
default: '3',
|
|
},
|
|
autosize: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
error: {
|
|
type: String,
|
|
defalut: '',
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
maxHeightInner: this.maxHeight,
|
|
inputValue: this.value,
|
|
}
|
|
},
|
|
computed: {
|
|
isDisabled() {
|
|
return this.disabled
|
|
},
|
|
errorInfo() {
|
|
return this.error
|
|
},
|
|
},
|
|
watch: {
|
|
value(val) {
|
|
this.inputValue = val
|
|
this.resizeTextarea()
|
|
},
|
|
inputValue(val) {
|
|
this.$emit('input', val)
|
|
this.$emit('change', val)
|
|
},
|
|
maxHeight(val) {
|
|
this.maxHeightInner = val
|
|
this.resizeTextarea()
|
|
},
|
|
},
|
|
mounted() {
|
|
this.resizeTextarea()
|
|
},
|
|
methods: {
|
|
$_onInput(event) {
|
|
this.inputValue = event.target.value
|
|
|
|
this.$nextTick(() => {
|
|
this.resizeTextarea()
|
|
})
|
|
},
|
|
$_onKeyup(event) {
|
|
this.$emit('keyup', event)
|
|
},
|
|
$_onKeydown(event) {
|
|
this.$emit('keydown', event)
|
|
},
|
|
$_onFocus() {
|
|
this.$emit('focus')
|
|
},
|
|
$_onBlur() {
|
|
setTimeout(() => {
|
|
this.$emit('blur')
|
|
}, 100)
|
|
},
|
|
$_calcTextareaHeight(textarea) {
|
|
// Triggers the textarea to repaint
|
|
textarea.style.height = 'auto'
|
|
|
|
let scrollHeight = textarea.scrollHeight
|
|
if (this.maxHeightInner && scrollHeight > this.maxHeightInner) {
|
|
scrollHeight = this.maxHeightInner
|
|
}
|
|
|
|
textarea.style.height = scrollHeight + 'px'
|
|
},
|
|
// public
|
|
resizeTextarea() {
|
|
if (this.autosize) {
|
|
this.$_calcTextareaHeight(this.$refs.textarea)
|
|
}
|
|
},
|
|
focus() {
|
|
this.$refs.textarea.focus()
|
|
},
|
|
blur() {
|
|
this.$refs.textarea.blur()
|
|
},
|
|
getValue() {
|
|
return this.inputValue
|
|
},
|
|
},
|
|
}
|
|
|
|
</script>
|
|
<style lang="stylus">
|
|
.md-textarea-item
|
|
&-msg
|
|
color textarea-item-color-error
|
|
.md-field-item-content
|
|
align-items normal
|
|
.is-disabled
|
|
.md-textarea-item__textarea
|
|
-webkit-text-fill-color textarea-item-color-disabled
|
|
color textarea-item-color-disabled
|
|
&__textarea
|
|
width 100%
|
|
-webkit-appearance none
|
|
border none
|
|
background transparent
|
|
outline none
|
|
resize none
|
|
box-sizing border-box
|
|
-webkit-tap-highlight-color transparent
|
|
appearance none
|
|
line-height textarea-item-line-height
|
|
font-size textarea-item-font-size
|
|
&::-webkit-input-placeholder
|
|
color textarea-item-placeholder-color
|
|
font-weight textarea-item-placeholder-weight
|
|
&.is-error
|
|
.md-field-item-content
|
|
hairline(bottom, textarea-item-color-error, 0, 4px)
|
|
</style>
|