I have a parent Vue component that renders an iframe which loads a child Vue component. When the user interacts with the child component it may load/reload another child component into the iframe.
I want to adjust the size of the iframe whenever it's content changes.
So I decided that when the current child hits the onMounted() hook it fires a signal to the parent (using postMessage).
The parent then queries the size of the document in the iframe and resizes the iframe to fit the content.
The problem I seem to be having is that the resize happens before the content is fully rendered, so the iframe is often the wrong size. If I set a 200 millisecond timeout it's fine.
Does this mean that onMounted() fires before the page is fully rendered? Any solutions to this?
The parent component:
<script setup>
import { usePostMessage } from '@/composables/usePostMessage';
import { ref } from 'vue';
const props = defineProps({
src : {
type : String,
required : true
},
id : {
type: String,
}
});
const frame = ref(null);
const isLoading = ref(true);
const methods = {
//adjust the iframe to fit the content
resizeFrame(){
const iframe = frame.value;
if (iframe) {
const iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
iframe.style.height = iframeDocument.body.offsetHeight + "px";
console.log('iframe size: ' + iframe.style.height)
}
},
onLoaded(){
isLoading.value=false;
}
};
//listen to events from the iframe
const { listenToPostMessage } = usePostMessage();
listenToPostMessage(['mounted'],methods.onLoaded);
listenToPostMessage(['resizeFrame'],methods.resizeFrame);
</script>
<template>
<div v-if="isLoading">
<slot name="loading" />
</div>
<iframe :src="src" ref="frame" class="w-full h-0" :id="id"></iframe>
</template>
In each child component:
onMounted(() => {
postMessageFromIframe({action:'resizeFrame'});
});