Skip to content
Advertisement

Why I can not call method of WebComponent?

I wonder why I cannot call a method defined in web-component if I attached this component via .append instead of using tag name inside the template. Below I am providing few examples. One is not working(throwing an error). I wonder why this first example is throwing this error.

Example 1

JavaScript

In this example, I am creating a web-component inside my js file and then directly appending it to document. In this case, I am getting an error that .hello doesn’t exist in my ComponentB. What’s more, the reference to my ComponentB instance which I get using .querySelector is NOT an instance of ComponentB.

Example 2

JavaScript
JavaScript

In this example, I am adding a web-component directly to html file. In this case, I am NOT getting an error and the reference to my ComponentB instance which I get using .querySelector is an instance of ComponentB.

Example 3

JavaScript

In this example, I am creating a web-component inside my js file and then directly appending it to document. In this case, I am NOT getting an error and the reference to my ComponentB instance which I get using .querySelector is an instance of ComponentB. The only one difference between Example 1 and Example 3 is that here I am using .innerHTML instead of deep cloned template.

From my point of view Example 1 is correct and should work. Can anybody explain to me why i am mistaken and why it is not working? Maybe you can also provide a solution how I can use <template> + .cloneNode inside js files to be able to access methods of my web-components created in such a way?

Advertisement

Answer

Simple explanation:

.innerHTML is synchronous

Thus <div><component-b></component-b></div> is immediately parsed when Component-A is constructed.

.append with Templates is A-synchronous, it will create the HTML in Component A shadowDOM, but leaves the parsing to later

I cleaned up your code to only show the relevant parts, and added console.log to show when Component-B is constructed

You can play with the append/append/innerHTML lines in Component A

(complex explanation) In depth video: https://www.youtube.com/watch?v=8aGhZQkoFbQ

Note: You should actually try and avoid this.componentB.hello style coding,
as it creates a tight coupling between components. Component A should work even if B doesn’t exist yet. Yes, this requires more complex coding (Events, Promises, whatever). If you have tight-coupled components you should consider making them 1 component.

JavaScript
Advertisement