I'm pulling my hair out on this one. I have a JavaScript class that clones a <template>
element and then is appended to the document body. I want to then manipulate that newly created element... but it always insists it's undefined.
Template
<template id="js-modalTemplate">
<aside class="o--modal" style="display: none">
<button class="o-modal__close-button">
Close
</button>
<div><iframe class="js-video" src=""></iframe></div>
</aside>
</template>
ES Module
export default class Modal {
constructor() {
const template = document.getElementById('js-modalTemplate');
const modalTemplate = template.content.cloneNode(true)
this.modalElement = document.body.appendChild(modalTemplate)
console.log(this.modalElement)
this.modalElement.style.display = "block"
}
}
Script element
<script type="module">
import VideoModal from "{{ Vite::asset('resources/js/components/Modal.js') }}"
window.testModal = new Modal()
</script>
The console.log output of the element sometimes appears in full, but sometimes it's empty (no changes to code)...
Empty fragment:
Fragment with content:
However I always get the following error, no matter what:
Uncaught TypeError: Cannot set properties of undefined (setting 'display')
And the element always appears in the DOM at the expected place.
Things I've tried
document.body
and adding defer
. (Neither of these things should be necessary because it's an ES Module anyway and so it automatically deferred.)window.onload
for similar reasonsThere's just something about using a <template>
that causes this issue, but I've never used them before so I don't know what!
You could get the top level element (the <aside>
) from the fragment through firstElementChild
before appending it to the DOM.
this.modalElement = modalTemplate.firstElementChild;
document.body.appendChild(modalTemplate);