createElement в пользовательском элементе разбивает шаблон

Я создаю два пользовательских элемента, оба добавляются в index.html по ссылке rel="import". Один - это контейнер со слотами, а другой - что-то, чтобы поместить число в слоты. Оба элемента имеют HTML-файл с шаблоном и ссылку на файл js, который определяет их как пользовательские элементы. Чтобы связать объявление класса пользовательского элемента с шаблоном HTML, который я использую:

class PuzzlePiece extends HTMLElement{

constructor(){
    super();
    console.dir(document.currentScript);
    const t = document.currentScript.ownerDocument.getElementById('piece-puzzle');
    const shadowRoot = this.attachShadow({mode: 'open'});
    shadowRoot.appendChild(t.content.cloneNode(true));
 }

Этот элемент головоломки и контейнер визуализируются правильно, и все это работает, когда вы вручную помещаете их в index.html light dom

<special-puzzle id="grid">
    <puzzle-piece id="hello"></puzzle-piece>
 </special-puzzle>

Однако, как только я попробую создать и добавить кусок головоломки, используя JS в index.html:

<script>
    const addToGrid = document.createElement("puzzle-piece");
    document.getElementById("grid").appendChild(addToGrid);
</script>

Я вижу новый кусочек головоломки в специальном паззле, но он не занимает слот, не рендерится, и в консоли есть ошибка:

Uncaught TypeError: Невозможно прочитать свойство 'content' с нулевым значением в новом PuzzlePiece (puzzle-piece.ts:8) в HTMLDocument.createElement (:3:492) в (index):37

Насколько я могу судить, проблема в том, что при использовании document.createElement браузер получает определение класса, но document.currentScript.ownerDocument отличается от того, когда он просто использует HTML-теги вручную. Я считаю, что из-за этого компонент не может найти свой шаблон. Это мой первый вопрос переполнения стека, поэтому любая обратная связь / помощь будет принята с благодарностью!

1 ответ

Решение

Решено благодаря потрясающему @Supersharp и их сообщению о переполнении стека

По сути, чтобы сохранить правильный document.currentScript.ownerDocument, мне нужно объявить его в переменной перед классом, а затем использовать эту переменную в классе.

Старый:

class PuzzlePiece extends HTMLElement{
constructor(){
super();
const t = document.currentScript.ownerDocument.getElementById('piece-puzzle');
const shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.appendChild(t.content.cloneNode(true));}

Новое:

var importedDoc = document.currentScript.ownerDocument;
class PuzzlePiece extends HTMLElement{
constructor(){
super();
const t = importedDoc.getElementById('piece-puzzle');
const shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.appendChild(t.content.cloneNode(true));}
Другие вопросы по тегам