Home > Net >  How to run a function to set height on all HTML tags of a particular type?
How to run a function to set height on all HTML tags of a particular type?

Time:09-24

I have some conditional renders of textarea elements in many places on a form that shows/hides these elements depending on what the user is doing. For example:

<li v-if="Form.Type === 1">
<textarea v-model="Form.Title" ref="RefTitle"></textarea>
</li>

There could be any number of textarea elements like above. What I need to do is resize these elements at certain points in the lifecycle (e.g. onMounted, onUpdated).

The function that gets triggered to do this is:

setup() {
...

const RefTitle = ref(); // This is the ref element in the template
    function autosizeTextarea() {
        RefTitle.value.style.height = "35px"; // Default if value is empty
        RefTitle.value.style.height = `${RefTitle.value.scrollHeight}px`;
    }

...
}

In the code above I am specifically targeting a known textarea by its ref value of RefTitle. I could test for its existence using an if(RefTitle.value) statement.

But how could I get all the textarea elements that may be rendered and then run autosizeTextarea on all of them?

I can get all the textarea elements like such:

setup() {
...

    function autosizeTextarea() {
        const AllTextareas = document.getElementsByTagName('TEXTAREA');
        for (let i=0; i < AllTextareas.length; i  ) {
        // How can I set the style.height = `${RefTitle.value.scrollHeight}px`; 
        // in here for each element?
        }
        
    }

...
}

But how can style.height be set on all of them?

CodePudding user response:

You could create your own custom component representing a textarea with the functionality in the component itself, so you don't have to get all textareas which are dynamically created.

It could look something like this:

<template>
  <textarea :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" ref="textarea" :style="styleObject"></textarea>
</template>
<script>
export default {
  emits: {
    'update:modelValue': null,
  },
  props: {
    modelValue: {
      type: String,
    },
    // Prop for dynamic styling
    defaultHeight: {
      type: Number,
      required: false,
      default: 35,
      validator(val) {
        // Custom Validator to ensure that there are no crazy values
        return val > 10 && val < 100;
      }
  },
  computed: {
    styleObject() {
      return {
        height: this.$refs['textarea'].value.scrollHeight ? `${this.$refs['textarea'].value.scrollHeight}px` : `${this.defaultHeight}px`,
    }
  },
</script>

That way you can even use v-model on it.

<li v-if="Form.Type === 1">
<custom-textarea v-model="Form.Title" :defaultHeight="45"></textarea>
</li>

The Template I provided is just to show you how a custom component could look like. You might have to fit it into your logic depending on when you actually want things to change/trigger.

CodePudding user response:

I have managed to do it like this:

 const AllTextareas = ref(document.getElementsByTagName("TEXTAREA")); //returns an object not an array
      for (const [key, value] of Object.entries(AllTextareas.value)) {
        AllTextareas.value[key].style.height = AllTextareas.value[key].scrollHeight ? `${AllTextareas.value[key].scrollHeight}px` : "35px";
      }
  • Related