Reputation: 14419
Currently I trigger an event to take the same height of the current element when the component is mounted, however this doesn't always work since it is sent once and if the element is resized it won't get sent again. Also I need to put a timeout since sometimes the chart in the componenet change sthe height after the ajax call.
How do I send this event ANYTIME the height of the current element is changed?
This is what I am currently doing:
mounted: function() {
setTimeout(function() {
this.$emit('resize', this.$el.offsetHeight);
},1000);
}
Upvotes: 22
Views: 25937
Reputation: 35400
In Vuetify 3, there is v-resize
directive (See docs) that can be used to monitor window resize events. This directive can be applied on any element, like this:
<v-row v-resize="onResize">
</v-row>
and in the handler, you can read new width and height of the window (or any other element for that matter), like this:
onResize () {
// window.innerWidth
// window.innerHeight
}
Upvotes: 0
Reputation: 2873
There is more Vue style solution based on ResizeObserver, but not supported in all browsers - yet
DOC: https://caniuse.com/#feat=resizeobserver
Examplum
data () {
return {
ro: null,
}
},
methods: {
onResize () {
this.$emit('resize', this.$refs.myElement.offsetHeight)
},
},
mounted () {
this.ro = new ResizeObserver(this.onResize)
this.ro.observe(this.$refs.myElement)
},
beforeDestroy () {
this.ro.unobserve(this.$refs.myElement)
}
Upvotes: 28
Reputation: 1848
I've had some issues getting ResizeObserver
to work in a Vue2 TypeScript project. Two approaches worked with (AFAICT) identical results:
Using the resize-observer-polyfill (which essentially wraps MutationObserver
). This required an import ResizeObserver from 'resize-observer-polyfill'
in my component.
Installing the @types/resize-observer-browser
npm package, based on this answer, and adding an entry to my tsconfig.json
:
{
"compilerOptions": {
...
"types": [
...
"resize-observer-browser"
]
}
}
This second approach didn't require any additional import and is the solution I'm favouring.
Both approaches offer the same ResizeObserver
API, e.g.
this.resizeObserver = new ResizeObserver((entries, observer) => {
log("Resize called", entries, observer)
})
this.resizeObserver.observe(this.$refs.canvas as Element)
(note: only tested in Chrome 88, Feb 2021)
Upvotes: 1
Reputation: 166
Until ResizeObserver becomes standard, you can use MutationObserver to keep track of the element's size. Codepen link
new Vue({
el: "#app",
data() {
return {
width: null,
height: null,
observer: null
};
},
mounted() {
//get initial dimensions. Mutation observer will observe mutations only
const box = this.$refs.box,
boxSize = box.getBoundingClientRect();
this.width = Math.trunc(boxSize.width) + "px";
this.height = Math.trunc(boxSize.height) + "px";
// initialize the observer on mount
this.initObserver();
},
//disconnect the observer before destroy
beforeDestroy() {
if (this.observer) this.observer.disconnect();
},
methods: {
initObserver() {
const box = this.$refs.box,
vm = this,
config = {
attributes: true
};
// create the observer
const observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
// check if the mutation is attributes and update the width and height data if it is.
if (mutation.type === "attributes") {
let {
width,
height
} = box.style;
vm.width = width;
vm.height = height;
}
});
});
// observe element's specified mutations
observer.observe(box, config);
// add the observer to data so we can disconnect it later
this.observer = observer;
}
}
});
.box {
text-align: center;
font-family: Arial;
box-sizing: border-box;
width: 150px;
height: 150px;
border: 2px solid red;
padding: 10px;
margin: 0 auto;
resize: both;
overflow: auto;
}
.size {
color: #2a9966;
font-weight: 600;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<!-- more info on refs: https://vuejs.org/v2/api/#ref -->
<div class=" box" ref="box">
<h4>Resize Me</h4>
<p>
<span>width: </span><span class="size">{{ width }}</span>
</p>
<p>
<span>height: </span><span class="size">{{ height }}</span>
</p>
</div>
</div>
Upvotes: 6