Hi, I’m using Builder.io content in a Vue.js app using Builder’s standard Vue.js sdk. I need to embed this Vue.js app inside an <iframe> tag on an existing webpage developed in PHP technology.
The Vue.js App.vue
code:
<script setup>
import { Content, fetchOneEntry, isPreviewing, getBuilderSearchParams } from '@builder.io/sdk-vue';
import { nextTick, onMounted, ref } from 'vue';
const content = ref(null);
const apiKey = '<api key>';
const canShowContent = ref(false);
const model = 'test-section';
onMounted(async () => {
content.value = await fetchOneEntry({
model,
apiKey,
options: getBuilderSearchParams(
new URL(location.href).searchParams
),
userAttributes: {
urlPath: window.location.pathname,
},
});
canShowContent.value = content.value ? true : isPreviewing();
setTimeout(() => {
console.log('scrollHeight: ', document.body.scrollHeight)
window.parent.postMessage({
msg: 'postScrollHeight',
scrollHeight: document.body.scrollHeight
}, '*')
}, 300)
});
</script>
<template>
<h1>Builder.io CMS Vue demo</h1>
<Content
v-if="canShowContent"
:model="model"
:content="content"
:api-key="apiKey"
/>
<div v-else>Content not Found</div>
</template>
The PHP container page:
<!DOCTYPE html>
<html lang="nl">
<head>
<script type="text/javascript">
window.addEventListener("message", (e) => {
const data = e.data;
if (data.msg == 'postScrollHeight') {
console.log(`postScrollHeight ${data.scrollHeight} received`)
document.getElementById("ifrmBuilder").height = data.scrollHeight;
}
});
</script>
<style>
iframe {
display: block;
background: #FFF;
margin: 0;
border: none; /* Reset default border */
width: 100%;
overflow: hidden;
}
</style>
</head>
<body id="body">
<div id="php">
<div class="container-fluid pt-md-2">
<iframe id="ifrmBuilder" src="http://localhost:5173" scrolling="no"></iframe>
</div>
</div>
</body>
</html>
When the Builder content is rendered inside the Vue.js app, I need to determine the scroll height of the Builder content from the Vue app’s body tag to set the height of the iframe. Next, I’m using window.postMessage()
to notify the iframe’s parent (the PHP container page) to set the height
of the iframe to the scrollHeight
of the Builder content.
However, the Builder content first needs to be rendered completely before you can even determine the scrollHeight.
The purpose of this: the Builder content needs to be seamlessly embedded inside (existing) PHP pages (without a visible iframe or scroll bars), using a Micro Frontend architecture. This allows you to leverage all the features of Builder content in a Vue.js app, such as your own custom Vue components, something that was not possible on a first attempt (trying to embed Builder content directly inside a PHP page).
So to integrate this seamlessly I wonder if there is a content loaded
or content rendered
event available in the Content component that fires when all content has been rendered in the browser DOM? As a temporary workaround, I’m now using a setTimeout() with a delay of 300ms to send the scrollHeight to the parent. Btw, using Vue’s nextTick()
after the await fetchOneEntry()
and setting the content.value
didn’t work out either - the nextTick()
fires too early.
Thanks in advance for any useful pointers!