I have a question regarding the Masonry layout update. How can I trigger it in the Vue.js (Version 3) lifecycle hook "updated()"?
I have a card grid view like in the following code (using Bootstrap 5 here), but struggle to update the Masonry layout when e.g. a card changes its size. I know that I can use layout() see documentation but I don't know how to call it in my example.
So my main problem is, that I don't know how to make my Masonry object accessible in the updated function when initialized in the mounted() function. How do I do that?
<template>
<div
class="row justify-content-left"
data-masonry='{"percentPosition": true }'
>
<div class="col-md-6 col-lg-4 col-xxl-3 mb-4 card-col">
<Card 1 />
</div>
<div class="col-md-6 col-lg-4 col-xxl-3 mb-4 card-col">
<Card 2 />
</div>
<div class="col-md-6 col-lg-4 col-xxl-3 mb-4 card-col">
<Card 3 />
</div>
<div class="col-md-6 col-lg-4 col-xxl-3 mb-4 card-col">
<Card 4 />
</div>
</div>
</template>
<script>
[imports ...]
export default {
name: "ComponentName",
components: {
[components ...],
},
mounted: function () {
// initialize masonry
this.$nextTick(function () {
var row = document.querySelector("[data-masonry]");
new Masonry(row, {
// options
percentPosition: true,
});
});
},
updated: function() {
//-->how to call the relayout of Masonry here?
}
};
</script>
To cache a reference the resulting Masonry
instance, just assign it to a property (you don't need reactivity on this instance, so attaching a property is fine):
export default {
mounted() {
this._masonry = new Masonry(this.$refs.masonry, ⋯)
},
updated() {
this._masonry.layout()
}
}
However, you'll notice that the this._masonry.layout()
call does not actually re-layout the masonry items (likely due to some limitation of the library). The only workaround I see is to recreate the Masonry
instance, and then you no longer need to cache a reference to it:
export default {
mounted() {
this.$nextTick(() => this.layout())
},
updated() {
this.layout()
},
methods: {
layout() {
new Masonry(this.$refs.masonry, ⋯)
}
}
}