Reputation: 14520
I'd like the v-textarea to grow and shrink according to how much text is placed in it, but I'm having this issue below with a v-textarea that is inside a v-layout that is closed (not expanded).
using this
<v-flex md8 px-1 offset-md2>
<v-textarea v-model="comments" @input="inputComments" rows="1" auto-grow :disabled="!editMode"></v-textarea>
</v-flex>
the field only shows 1 row and doesn't auto-grow. You can see the 2nd line is NOT showing completely.
and when I remove "rows="1" then this is what I see (extra white space) because the default rows is 5 for a textarea
Isn't there a way to get it to autogrow based on the lines of text or maybe re auto-grow it after it is expanded? I thought that was how it was supposed to work, but I could be wrong!
FYI - this textarea is in a hidden section, it only displays if the section is expanded. The other textareas I have on the page (not in a expanded area) show/auto-grow just fine!
Upvotes: 8
Views: 8382
Reputation: 2011
I appreciated the other answers but wasn't fully satisfied because they were causing flashing or were delayed due to timers, etc.
What I did was use the v-resize directive to capture when the window resizes and then call calculateInputHeight(). For example, here is a template:
<div ref="container">
<v-textarea :value="longText"
label="Text"
rows="1"
auto-grow
filled
hide-details
class="ma-4"
ref="textarea"
v-resize="onWindowResized"></v-textarea>
</div>
And the component code:
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: {
textareaWidth: undefined,
longText: [...Array(26)].map((el, i) => String.fromCharCode(97 + i).repeat(10)).join(' ')
},
methods: {
onWindowResized() {
let textareaWidth = this.$refs.container && this.$refs.container.offsetWidth;
if (textareaWidth !== this.textareaWidth) {
this.textareaWidth = textareaWidth;
this.$refs.textarea.calculateInputHeight();
}
}
}
})
This is allowing the text area to resize accordingly, without the flashing. Here is the full JSFiddle: https://jsfiddle.net/CodeVirtue/t0ex7pzu/
Upvotes: 0
Reputation: 391
I had similar issue when v-textarea with auto-grow is inside of v-expansion-panel-content
Just wrap it with v-lazy component and auto-grow should work as expected
<v-expansion-panel-content>
<v-lazy>
<v-textarea
:key="autoGrowHack"
v-model="textAreaVal"
auto-grow
></v-textarea>
</v-lazy>
</v-expansion-panel-content>
Upvotes: 8
Reputation: 994
I also stumbled upon this issue, which seems to be related to this https://github.com/vuetifyjs/vuetify/issues/6995.
Here's what I did:
<template>
<div>
<v-textarea
...
maxlength="1024" :rows="rows" auto-grow
:disabled="isDisabled"
...
>
</v-textarea>
</div>
</template>
<script>
export default {
name: "MyComponent",
props: {
isDisabled: {
type: Boolean
},
},
data() {
return {
rows: 3,
},
},
mounted() {
if (this.isDisabled) {
this.rows = 5;
}
},
</script>
In my case I have a prop isDisabled
that checked if v-textarea
should be disabled or not. Because I use a v-stepper
and this component is not the first one shown, the autogrow bug kicks in.
Originally, v-textarea
should've been only 3 rows and would expand based on how many characters there are.
I created a new property rows
and set it to a default value.
When the prop isDisabled
is true
, I change the value of rows
to 5
when the component is mounted. I chose the value 5
because the 1024
allowed characters seem to fit in just fine in my case.
Hope someome finds this useful!
Upvotes: 0
Reputation: 2044
In my case v-textrea
is hidden sometimes and when it's shown again it height doesn't get calculated properly;
Found nothing better than
<template>
<!-- . . . . .-->
<v-textarea
ref="vTextarea"
:value="vTextareaValue"
auto-grow
hide-details
rows="1"
single-line
/>
</template>
<script>
export default Vue.extend({
data() {
return {
vTextareaWasMounted: false,
};
},
updated: function () {
let vTextAreaMounted = !!this.$refs.vTextarea;
if (vTextAreaMounted && !this.vTextareaWasMounted) {
let delays = [30, 60, 100, 200];
delays.map((delay) => {
setTimeout(() => {
if (this.$refs.vTextarea) {
console.log(this.$options.name + ': vTextarea force calculateInputHeight')
this.$refs.vTextarea.calculateInputHeight();
}
}, delay)
});
}
this.textareaWasMounted = vTextAreaMounted;
},
});
</script>
Timers are ugly but I don't know how to improve this solution yet
Upvotes: 0
Reputation: 969
I have had a similar problem, and solved it by setting the key
attribute of the v-textarea
to a variable and changing said variable manually, forcing the component to re-render. After the re-render, auto-grow
worked correctly.
<template>
<v-textarea
:key="autoGrowHack"
v-model="textAreaVal"
auto-grow
></v-textarea>
</template>
<script>
export default {
data() {
return {
autoGrowHack: false,
textAreaVal: "lorem ipsum",
}
},
methods: {
forceReRender() {
this.autoGrowHack = !this.autoGrowHack;
}
},
}
</script>
As far as when to call the forceReRender
function, that's going to depend on specifics in your code. I was using this v-textarea
inside a component on a v-stepper
tab, and found that triggering the switch when the v-stepper
's step is changed to the one with this component on it made it work.
I'm guessing this is related to the following open bug on vuetify that also relates to auto-grow: https://github.com/vuetifyjs/vuetify/issues/6995
Upvotes: 10