top of page
Search
Writer's picturegirizano

HTML-component not running in Publish Mode (Google Sheets Example)

Updated: Jul 2, 2018

Abstract

This article describes how to display a different Google Sheet (per Item) on every Wix Dynamic page. The data for the sheet is read from the database and then displayed inside the Wix HTML-component.


The problem

Let us assume that we have a Dynamic page with an html-component called

Also, after having the Google sheet published, we would have (after a bit of tweaking, more on that later) a code snippet to it like this;


<iframe src="https://docs.google.com/spreadsheets/d/e/2PACX-

1vTPyCGtMhxTHDVxVQ2bCAZjSrSp2f2YAwR1kYawPns0BfPrQ22L_COl6w8BqhYuIAWZa93r2txY4f3_

/pubhtml?

gid=1932313782&amp;single=true&amp;widget=false&amp;headers=false&amp;chrome=fal

se" width="750" height="1500" style="border:0px"></iframe>




At first, I sent the Google code for that sheet to the html-component using this HTML inside

the component´s properties:



<html>

<head>

<script type="text/javascript">

// when a message is received from the page code

window.onmessage = (event) => {

if (event.data) {

document.getElementById("GoogleSheetsDocs").innerHTML = event.data;

}

};

</script>

</head>

<body>

<div id="GoogleSheetsDocs"></div>

</body>

</html>


using, inside the Wix Page, this to trigger it;


$w("#ifrGoogleSheetsDocs").postMessage(txtMessage);

$w("#ifrGoogleSheetsDocs").show();


txtMessage held the Google Sheets snippet, read from the database. The html-component was HiddenOnLoad, so the .Show(), well, … shows it.

The problem was: this worked fine in Preview Mode, but in Publish mode, it did not show the

Sheet at all.


The cause

Although the above code was inside a $w.onload, it turned out that this onLoad only is valid for the main page, NOT the html-components inside it.

When your page is run and it encounters the html-component, a separate process is spawned,

completely asynchronous from the main page. So what then happens is this:

1: the main page with all the code does NOT wait for the html-component to load, it just goes

on with the next instruction, while

2: in another process, the html-component is loaded, the html is parsed, the DOM populated,

the html executed and THEN the component is ready.

And that moment may come later then the main page encounters the above .postMessage. So, the main page sends a message (holding the Google Sheet html) earlier than the htmlcomponent is ready. The result is that the main page sends a message to the component that doesn´t listen yet and therefore the html is not received, thus not displayed.


Preview vs. Publish

But why did it work in Preview mode and not in Publish Mode? Well, have you never noticed

that when you press Preview, the screen doesn´t flicker and the page is not reloaded? That is

because, if you look at the Wix code inside your browser, Preview Mode is just a CSS-class that turns off a couple of controls when in Editing mode.

This means, the html-component was already loaded (you have been looking at it for half an

hour while in Editing Mode) and thus it was more than ready to receive the message. But in

Publish Mode, everything has to be loaded fresh, and there we run into our problem.


The solution

All Wix examples regarding the html-component let the Main program start a conversation and then the html-component answers. What we want is to turn it around: that the htmlcomponent starts the conversation and the main program listens and answers back.

So, we have to roll our own “onReady” for the html-component. Only when it is ready to

receive a message, then we send the Google Sheets snippet. So how do we do that?

Well, it goes like this:

1) when the component is ready (the BODY onLoad = ... inside its HTML), send a message to

the main program that it is so, using window.onmessage inside the html-component´s html;

2) the main program must wait until it receives a message from the component (using the

.onMessage from the html-component). Only then will it send the Google Sheets string

using .postmessage

3) the html inside the component must now put the received code into a block (like a DIV) to

be displayed using .innerHtml.

4) done


Update 02/07/2018

Huge problems developing the alternative Date Picker, using the html-component (HC). Suddenly, instead of the HC loading AFTER the Wix page ($w), it consistently loaded BEFORE. That meant that the "heart beat" was never received, because $w had not loaded yet.

According to Wix this was an infrastructural problem, where, due to network latency, one part might indeed load before the other, without any guarantee of order.

Solution: throw it max. twice: in the $w.onReady, just send the html for the HC. If the HC is not loaded yet, it will not be received. But if it loaded before $w, it will. So it will receive html BUT the heart beat back to the main Wix page will be ignored (because $w has not loaded yet), so it won´t be sent twice.

In the other case, where the HC loads AFTER $w, it will work as described: "hello, I´m ready" -> send HTML -> done. The html sent BEFORE the component loaded (in $w.onReady will be ignored, since the HC was not ready yet to receive.

Yes, I know this sounds complicated. Don´t blame me.


The code

This goes into the html-component:


<!doctype html>

<html>

<head>

<script type="text/javascript">

window.onmessage = (event) => {

if (event.data) {

document.getElementById("GoogleSheetsDocs").innerHTML = event.data;

}

};

function sendLoadMessage () {

window.parent.postMessage("LoadOk", "*");

}

</script>

</head>

<body onload="sendLoadMessage ();" style="background-color:white;">

<div id="GoogleSheetsDocs"></div>

</body>

</html>


Note: the “LoadOK” message could be anything, like “You´re holding it wrong” or

“Done”. It´s not about WHAT the component sends, it´s about THAT it sends.

The white background color is of course up to you to set differently, or not at

all.


This goes into the main program: datasetname and fieldname (and maybe ifrGoogleSheetsDocs) should be replaced by your own

names.


let urlMessage = $w('#datasetname').getCurrentItem().fieldname;

$w("#ifrGoogleSheetsDocs").onMessage( (event) => {

$w("#ifrGoogleSheetsDocs").postMessage(urlMessage);

});


Google Sheets tweaks

Google Sheets gives us a code snippet which we can paste into a page. Thing is, if you use it

as as, it shows a sheets with tabs and a bottom bar. I wanted to get rid of that and only show

the sheet itself. In Google Sheets documentation I found these settings:

•gid=1674242611 - This is the sheet ID

•range=A1:B14 - The range you want to display.

•widget=false - If false, there's no sheet tab displayed at the bottom

•headers=false - Row numbers and column letters are not displayed.

•chrome=false - Title and footer is not displayed.

Also, width and height can be set to a percentage. If you want to get rid of the gridlines, you

will have to set that inside the sheet itself.


All statements made are mine and not endorsed or verified by Wix.

Change log

09 nov 2017 : initial write-

1,948 views1 comment

Recent Posts

See All

1 commentaire


Les commentaires ont été désactivés.
poolshark314
19 nov. 2018

Giri, thanks for writing this. You are a great resource in the Wix community. Is urlmessage supposed to be the actual URL?

J'aime
bottom of page