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";
}