'VueJs: How to update the width of an element based on another?
I am building a Trivia app, and I have an <h1> element that changes every 10 seconds. I want to match the width of a radio button group component (b-form-group is a Bootstrap-Vue component) with the width of the <h1> element. Something like this:
I tried using watchers to update buttonWidth whenever the value of question changes. But, with this code, the width of the button group seems to match the width of the previous question instead of the current one. I also tried other properties like updated, mounted, created. I am just not able to get it to work correctly. Is there an easier way to match the width of two elements?
<template>
<div>
<div id="question">
<h1 ref="quest">{{ question }}</h1>
</div>
<b-form-group>
<b-form-radio-group :style=getWidth
ref="opts"
:options="options"
buttons
stacked
button-variant="outline-primary"
size="lg"
name="radio-btn-stacked"
></b-form-radio-group>
</b-form-group>
</div>
</template>
Under my Script I have:
export default {
props: ['question', 'options'],
data() {
return {
buttonWidth: '0 px',
};
},
methods: {
},
watch: {
question() {
// console.log('Updating button width to ', this.$refs.quest.clientWidth);
this.buttonWidth = `width: ${this.$refs.quest.clientWidth}px;`;
},
// immediate: true,
},
computed: {
getWidth() {
return this.buttonWidth;
},
},
};
Solution 1:[1]
To get it working with a watch you'd need a $nextTick, otherwise the component won't have re-rendered yet and you'll still be measuring the old width:
watch: {
question() {
this.$nextTick(() => {
this.buttonWidth = `width: ${this.$refs.quest.clientWidth}px;`;
})
}
}
It should also be possible to get this working with the mounted and updated hooks instead of a watch. You shouldn't need $nextTick if you do it that way. You mentioned that you've tried that in the question but without seeing the code you tried it's difficult to know why that didn't work for you.
Also, it's not clear why you have a computed property called getWidth. Why not just use buttonWidth directly?
Solution 2:[2]
My mistake was using the clientWidth of the h1 tag. This wasn't returning the width of the text in pixels, instead, it was returning the entire width of the div. Here is the solution that worked for me:
<template>
<div class="text-center center">
<div id="question">
<h1 ref="quest"><span ref="span">{{ question }}</span></h1>
</div>
<b-form-group>
<b-form-radio-group :style=buttonWidth
ref="opts"
:options="options"
buttons
stacked
button-variant="outline-primary"
size="lg"
name="radio-btn-stacked"
></b-form-radio-group>
</b-form-group>
</div>
</template>
<script>
export default {
props: ['question', 'options'],
data() {
return {
buttonWidth: 'width: 500px',
value: 0,
};
},
watch: {
question() {
console.log('Watcher is updating buttonWidth to ', this.$refs.quest.clientWidth);
this.$nextTick(() => {
console.log(this.$refs.span.offsetWidth);
this.buttonWidth = `width: ${this.$refs.span.offsetWidth}px;`;
});
},
},
};
</script>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | skirtle |
| Solution 2 | whoacowboy |
