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 ponent app.module
:
<!DOCTYPE html>
<body>
<mp-app-root></mp-app-root>
</body>
</html>
the app module is a simple web ponent. 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>
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 ponent app.module
:
<!DOCTYPE html>
<body>
<mp-app-root></mp-app-root>
</body>
</html>
the app module is a simple web ponent. 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>
Share
Improve this question
asked Jul 24, 2020 at 11:37
CenasaCenasa
5991 gold badge12 silver badges33 bronze badges
3
- Can you try this in your browser and tell us if it works? jsfiddle/1j87xtqe – Guerric P Commented Jul 24, 2020 at 11:53
- @Guerric P yes it works. hm this is strange. – Cenasa Commented Jul 24, 2020 at 11:58
- Well it might help you find the cause, I have no clue!. – Guerric P Commented Jul 24, 2020 at 12:00
1 Answer
Reset to default 7You 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)
See:
- (long read) Dev.to blog: Developers haven't connected with the connectedCallback (yet)
- How to Get the Contents of a Custom Element
- wait for Element Upgrade in connectedCallback: FireFox and Chromium differences
- Create WebComponent through createElement
working code: (read that long blogpost)
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')