I have defined a custom element and I want to execute a script only when the custom element is upgraded to its registered type. The use case is that I must call a custom method.
My main html file looks like this:
<project-list></project-list>
<script>
var project_list = document.getElementsByTagName("project-list")[0]
project_list.custom_method("some_data");
</script>
The custom element is registered in a HTML import like this:
<script>
"use strict";
var currentScript = document._currentScript || document.currentScript;
class ProjectList extends HTMLElement {
createdCallback(){
console.log("created");
}
custom_method(data) {
console.log("custom_method() OK");
console.log(data);
this.innerHTML = data;
}
}
document.registerElement("project-list", ProjectList);
</script>
My question is simple: how to make sure the script in the main html file is called only after the custom element gains its custom_method
method?
I'm looking for an elegant solution. Something that the spec authors would have thought of. I don't mind changing the architecture quite a bit (for example by moving the javascript from the main file into another custom element if that is necessary).
The functionality of a custom element is defined using an ES2015 class which extends HTMLElement . Extending HTMLElement ensures the custom element inherits the entire DOM API and means any properties/methods that you add to the class become part of the element's DOM interface.
“What's The Point Of Custom Elements?” # The basic idea is that if you create an element that always performs the same role and has the same set of properties and functions applied to it, then you should be able to name it after what it does.
Steps involved in creating a Custom HTML Element:Create a new Class representing the New Element (ES6) Extend the class from “HTMLElement” Add “connectedCallback” function to the class to access DOM Element when the element is added to the document. Access the Custom DOM Element using “this” keyword.
Execute a script when the element is being clicked in HTML? Execute a script when the element is being clicked in HTML? Use the onclick attribute to execute a script when the element is clicked in HTML. You can try to run the following code to implement onclick attribute −
Once a custom element is defined, we can use it on par with built-in HTML elements. That’s great, as HTML dictionary is rich, but not infinite. There are no <easy-tabs>, <sliding-carousel>, <beautiful-upload> … Just think of any other tag we might need. We can define them with a special class, and then use as if they were always a part of HTML.
Customized built-in elements – extending built-in elements, like a customized button, based on HTMLButtonElement etc. First we’ll cover autonomous elements, and then move to customized built-in ones.
You can use window.customElements.whenDefined ("my-element") which returns a Promise that you can use to determine when an element has been upgraded. window.customElements.whenDefined ('my-element').then ( () => { // do something after element is upgraded })
Sync HTML Import
As suggested by @dandavis, because of the sync
default behaviour of the <link>
and <script>
elements, you just have to put your tags in the right order: registration before method call.
Or instead you can call your custom method when the DOMContentLoaded
or the window.onload
event is fired, as below:
window.onload = function()
{
var project_list = document.getElementsByTagName("project-list")[0]
project_list.custom_method("some_data")
}
<project-list></project-list>
<script>
"use strict";
var currentScript = document._currentScript || document.currentScript;
class ProjectList extends HTMLElement {
createdCallback(){
console.log("created");
}
custom_method(data) {
console.log("custom_method() OK");
console.log(data);
this.innerHTML = data;
}
}
document.registerElement("project-list", ProjectList);
</script>
Async HTML Import
If for some reasons you want to load your HTML Import file asynchronousely, you can wait for the link.onload
event. At this time the |<script>
inside the import has been already exectued, the custom element registered and created.
<html>
<head>
<title></title>
<meta charset="utf-8" />
<link rel="import" href="projectList.html" id="projectList" async>
<script>
projectList.onload = function ()
{
console.log( "import {loaded}" )
var project_list = document.getElementsByTagName( "project-list" )[0]
project_list.custom_method("some_data")
}
</script>
</head>
<body>
<project-list id="pl"></project-list>
<script>
console.warn( "custom_method is " + pl.custom_method ) //undefined
</script>
</body>
</html>
With WebComponents.js polyfill
In this situation the polyfill won't instantiate the created object immediately after the import is loaded. Instead you should listen to the WebComponentsReady
event:
document.addEventListener( "WebComponentsReady", function ()
{
console.log( "WebComponentsReady" )
var project_list = document.getElementsByTagName( "project-list" )[0]
project_list.custom_method( "some_data" )
} )
It works with Firefox, IE 11, and also with Chrome.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With