chuckd
chuckd

Reputation: 14520

Vue.js vuetify v-textarea not auto growing correctly inside v-layout that's un expanded

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.

enter image description here

and when I remove "rows="1" then this is what I see (extra white space) because the default rows is 5 for a textarea

enter image description here

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

Answers (5)

Agendum
Agendum

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

Sergey
Sergey

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

Carol-Theodor Pelu
Carol-Theodor Pelu

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

d9k
d9k

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

Daniel Smedema
Daniel Smedema

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

Related Questions