I’ve been getting to know custom elements and was able to integrate a 3rd party app API using a “click” addEventListener for the custom element with this code:
Passing data from page to custom element in onReady
But what you can do I think is you can pass an empty data or anything from your page code to custom element with custom element APIs (setAttribute) inside the $w.onReady in this way you can fire any code when custom element recieve the attirbute value say pageLoaded.
// Inside Custom Element
// Attributes keys that's listened for changes
static get observedAttributes() {
return ["pageLoaded"];
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === "pageLoaded") {
// fire anything you want here
}
}
connectedCallback (better)
Another way which is more simple and better I think; you can use built-in connectedCallback event inside custom elements.
connectedCallback() {
// fire any code you want here (this event will be fired when custom elements loaded)
};
I hope it helps. If you can solve the problem mark this as solution so thread will be marked as solved.
I was using the connectedCallback() event but thought that I had to use an addEventListener under that.
Now I see that I can just put the code I want under it without the event listener and it fires when the custom element loads.
FYI I tried the window.addEventListener(‘load’) and couldn’t even get a console log message to fire. Not sure why.
Edit: I spoke too soon. Running the code immediately below the connectedCallback() event does nicely trigger a console log, but doesn’t seem to let me use dispatchEvent to define the event to use in the page code.
I would love to be able to use the window.addEventListener(‘load’) option under connectedCallback(), but it’s not working!
I would love to be able to use the window.addEventListener(‘load’) option under connectedCallback(), but it’s not working!
This won’t work even if the listener attached because page is already loaded. And you also don’t need this. If you want to run some code when page loads/custom element loads you can run that code directly under connectedCallback()
…but it doesn’t work this way (maybe because the timing clashes with onReady?).
It DOES work if I simply use a “click” event listener (same page code):
But I want to be able to pull the Memberspace ID automatically rather than with a click.
FYI getMsReadyPromise() is from the Memberspace API as follows:
const getMsReadyPromise = () =>
new Promise(resolve => {
if (MemberSpace.ready) {
// Ready event is already fired, so let's not wait for it, it will not be fired again
resolve(window.MemberSpace.getMemberInfo());
}
else {
// MS widget is not yet ready, let's subscribe for the event
const handleReady = ({ detail }) => {
resolve(detail);
// Unsubscribe ourselves, this allows GC to collect all related memory
document.removeEventListener('MemberSpace.ready', handleReady);
};
// Listen to ready event
document.addEventListener('MemberSpace.ready', handleReady);
}
});
It would be enough if I could just store the data in the memory. Please let me know if you have any suggestions!
I previously tried setTimeout but I put in a long duration >350ms thinking that the more I wait the better. But it seems 50 ms is catching it at just the right moment.
I wonder if this is going to be reliable, or might there be ebbs and flows depending on whether there’s a lag on either side?
Edit: For some pages, the mobile version isn’t working, for example. Is it possible to do a container.addEventListener for “onViewportEnter”?
You can try to check docs about elements for event listeners if onViewportEnter supported. I think 50ms will be ok but you can test on different devices/browsers to check it.
I’m doing some research but couldn’t find a list of event listeners. I’ll keep looking.
I thought your idea about using setAttribute was a great one - I tried it alone and with an onViewportEnter but for some reason it seems to not be hearing the signal on the custom element side.
The latest version I have is this:
class MemberspaceUp extends HTMLElement {
constructor() {super();}
static get observedAttributes() {
return ["pageLoaded"];
}
attributeChangedCallback(name) {
if (name === "pageLoaded") {console.log("page loaded")}
}
}
customElements.define('ms-up', MemberspaceUp);
I think the root problem is “timing” the execution of both logic, onReady() and the Custom Element.
When onReady() starts it’s logic the Custom Element is already rendered. It’s there for you to reference it but it’s still a HTMLElement (or whichever class you are extending).
Only after upgrade (throught define) the Custom Element will have your custom logic and respond to your choice of observedAttributes.
I had the same problem and found out it still a general problem with Custom Elements: to find when its upgrade will happen.
So sometimes onReady() happens before connectedCallback() other times after. You can see it from logging and reloading a page.
Timeout can solve it but demands fine tuning and I find it risky.
Solution I found:
Attributes changed before the upgrade stick after the upgrade.
In the Custom Element connectedCallback() I check for this atribute:
if (this.getAttribute('onreadystate')=='onreadyhasstarted')
// I know onReady() has already started
else
// I know this is happening before onReady()
Pay attention: any $w(‘#customElement’).on(‘event’) which is processed before the customElements.define() will not catch because it is referencing a #customElement which has not yet been upgraded to the Class you designed.
I wanted to clarify, under the “else” statement, would you then put a setTimeout (although it seems this may defeat the purpose), or how would you deal with the fact that onReady hasn’t happened yet?
Maybe take your logic out of connectedCallback() into a doSomething() which will be triggered (attributeChangedCallback()) by the change in the attribute (in onReady()).
…and encountered this problem: even though the “if” statement was able to catch the getAttribute every time, it wouldn’t fire my logic (the dispatchEvent doesn’t seem to work). If I remove the if/else and just have connectedCallback with a 50ms setTimeout, the logic fires.
I wonder if there’s another factor (other than onReady) that is affecting the timing issue?
Maybe the $w(‘#customElement’).on() has been processed before the upgrade of the Custom Element (define) thus being lost and not firing.
That is the worst situation. I am still looking for a solution to in onReady() verify if the Custom Element has upgraded because only then I can make use of $w(‘#customElement’).on().