I am building an application with Web Components and only vanila javascript. I want to use vaadin-router for routing.
In my index.html I only display the web component app.module
:
<!DOCTYPE html>
<body>
<mp-app-root></mp-app-root>
</body>
</html>
the app module is a simple web component. It should display the routing module in a template. The Shadow DOM is optional.
app.module.js
import Template from './app.module.template.js'
class AppModule extends HTMLElement {
connectedCallback() {
this.innerHTML = Template.render();
}
}
customElements.define('mp-app-root', AppModule)
The template simply renders the tag, where the routing should happen.
app.module.template.js
import './routing.module.js'
export default {
render() {
return `${this.html()}`;
},
html() {
return `<script type="module" src="./routing.module.js"></script>
<app-routing-module></app-routing-module>`;
},
}
As you can see, i am importing the script routing.module.js
- It also works, when im console.logging something
Now, I am using vaadin-router for routing and I want to access the <app-routing-module>
-Tag with querySelector like this:
const outlet = document.querySelector('mp-app-root').querySelector('app-routing-module')
but it is always null.
console.log(document.querySelector('mp-app-root')
works and prints the following:
<mp-app-root>
<app-routing-module></app-routing-module>
</mp-app-root>
You get null
, you can't access the lightDOM
Because the connectedCallback
fired on the opening tag
This is considered the correct implementation of the W3C Web Components standard
(Firefox got it wrong until they fixed it in 2021)
setTimeout( () => {
const outlet = document.querySelector('mp-app-root')
.querySelector('app-routing-module')
});
All WebComponent libraries do something similar under the hood;
delay execution till the Eventloop is empty, and the DOM is ready to accept your selections/additions.
Note: querySelector
takes a selector, so you can write:
const outlet = document.querySelector('mp-app-root app-routing-module')