Builder page is missing pictures and interactivity

I’m trying to bring in a Builder “Page” model instance like this:

builder.get('page').promise().then(content => {
                    this.content = {
                        html: content ?
                            content.data.html :
                            '<page-not-found />'
                    }
                })
...
this.content.innerHTML = this.content.html

I’m doing it this way, instead of using the <builder-component> so that an extra fetch doesn’t happen (in the builder-component). But I’m finding that when I do it this way the rendered page is missing its images and interactivity.

FYI this method does seem to work when the model is of type “Section”.

I am bringing in the Builder SDK as follows in our index.html:

<script async src="https://cdn.builder.io/js/webcomponents"></script>

Hi @Canuckaholic, can you please provide more details about your use case for web components and your tech stack? It looks like you are using React so you can just use our React SDK and <BuilderComponent>.

The Web Components API is intended for those who don’t use a modern framework. <builder-component> is the custom HTML element that the script will make interactive so it is necessary if using the web components approach.

Hi @ancheetah we are not using React; we are using Lit (formerly Lit Element) and web components. And I would argue that this approach is just as modern as using React :wink:

So if I’m using the web component approach, how can I execute the code I posted above and NOT do a fetch twice for the content (once in the get() and another time by the web component itself)?

I also want to point out that in the sample code given for rendering a ‘Page’ using JS, it is going to result in the same double fetch of the content, once in the get() and a second time in the <builder-component>. To be honest, it feels like most of Builder’s development and testing is going into the React side of things, but web components are arguably the future. :slight_smile:

builder.get('page').promise().then(content => {
  // Add the HTML to the element needed, wrapping with our webcomponent library
  // to fill in any needed interactivity (e.g. lazy loaded images, interactive tabs, etc)
  document.querySelector('#my-page').innerHTML = `
    <builder-component model="page">${content.data.html}</builder-component>
    <script async src="https://cdn.builder.io/js/webcomponents"></script>
  `
});

Hi @ancheetah any more thoughts or information for me?

Hey @Canuckaholic, my apologies. Still waiting for confirmation from my team if this is a bug. I was able to reproduce that by adding web components with the builder.get() method from @builder.io/sdk, the Builder component does seem to lose interactivity and images. I’ll go ahead and ticket this in our system for now and let you know if I have any updates.

@Canuckaholic it appears there are a couple updates that need to be made to that Vanilla JS snippet. Until that change is live, here is what you need to do to get your content working:

//index.js
builder.get('page').promise().then(content => {
  // Add the HTML to the element needed, wrapping with our webcomponent library
  // to fill in any needed interactivity (e.g. lazy loaded images, interactive tabs, etc)
  document.querySelector('#my-page').innerHTML = `
    <builder-component 
        model="page"
        api-key="123456789"
    >
       ${content.data.html}
    </builder-component>
  `
});

//Add this in your index.html or wherever you load the index.js script above
<script async src="https://cdn.builder.io/js/webcomponents"></script>

Notice that the API key should be added to the <builder-component> and the web components script should be moved out of the innerHTML assignment.

thanks @ancheetah, I’ve tried this approach already, however, and it doesn’t work. Also note, as per my previous message, that this code is going to result in a double fetch of the content, once in the get() and a second time in the <builder-component> . So it’s not the most efficient.

@ancheetah any updates on this?

Hey @Canuckaholic, @ancheetah has been out this week and I have been stepping in to help out, apologies for delay on my part!

So the double call is actually expected in this instance.

Essentially, the builder.get() call is intended to happen on the server and will pass the content to your page without any JS (hence the lack of images and JS interactivity)

On the frontend, the will rehydrate with the lazy loaded images and your JS interactivity. If separated on server and client correctly, it would only result in a single call in each environment.

If you are ONLY looking to use client-rendered content and limit to a single call you can just remove the builder.get() and on your frontend use:

 <script async src="https://cdn.builder.io/js/webcomponents"></script>
...
 <builder-component
      model="page"
      api-key="YOUR_API_KEY"
    ></builder-component> 

This won’t be server rendered, but will only have the single call and load all your content, HTML and JS. The code above is selecting your top page content, but if you want to target a specific content entry, you can use the entry attribute as outlined here: Builder.io Webcomponents API - Builder.io.

Hope that helps and of course let us know if you have any other questions!