solid icon indicating copy to clipboard operation
solid copied to clipboard

[html] Unable to use a `<template>` element in `html` template

Open trusktr opened this issue 1 year ago • 5 comments

Describe the bug

This causes an error:

import html from 'solid-js/html' 

html`
  <div>
    <template>
      <h1>Example</h1>
    </template>
  </div>
`

Error:

Uncaught TypeError: Cannot read properties of null (reading 'firstChild')

Your Example Website or App

https://playground.solidjs.com/anonymous/5dd52803-e570-4f6e-a72d-0ef56944996f

Steps to Reproduce the Bug or Issue

see console

Expected behavior

expect to use a <template> element like normal HTML

Screenshots or Videos

No response

Platform

  • OS: macOS
  • Browser: Chrome
  • Version: 1.8.5

Additional context

No response

trusktr avatar Nov 26 '23 18:11 trusktr

Are you expecting dynamic expressions? Just wondering because templates walk differently... Is the expectation that walks just stop? If so dynamic inserts would break from a mismatch. I guess if it is a template it would be .content.firstChild.

ryansolid avatar Nov 29 '23 09:11 ryansolid

I've been trying to solve this issue for the last two days but couldn't succeed.

The error comes from the lit-dom-expressions package. The package mostly uses node properties like firstChild, nextSibling, and children, but these properties are empty in the template element. It exposes all of its content to the content property.

femincan avatar Nov 29 '23 12:11 femincan

@femincan exactly. It is a very different sort of element. It would require custom code generation for just that case. I don't think Solid's JSX handles it properly either. I've never bothered trying to get the transform working for them. It should be doable I think but it requires a little bit of specific work.

ryansolid avatar Dec 04 '23 17:12 ryansolid

In my case, I'm not trying to interpolate anything inside the <template>. But I would imagine interpolating should work. I could imagine someone could interpolate to update the template content, then stamp that out in its new shape each time using cloneNode.

In my case, I use it to write HTML code for live code demos using a <live-code> custom element (uses a <code-mirror> element under the hood), and the purpose of the <template> is so that the content is not rendered or instantiated by the browser.

For example, everything inside the <template> will become editable code with live preview:

<live-code>
  <template>
    <!-- Everything inside of here is just source code for a demo -->
    <head>
      <!-- we don't want this script to execute -->
      <script>...</script>
    </head>
    <body>
      ...
    </body>
  </template>
</live-code>

Example usage:

https://github.com/lume/lume.github.io/blob/f9d8da461260e94b076d5e6620abb73a0ce5c9d7/guide/positioning/README.md?plain=1#L28-L43

This is the result:

https://docs.lume.io/guide/positioning/

Now that I think about it, my <live-code> element currently doesn't observe changes to <template>, it only uses the initial content. But an upgrade would be for it to update the code editor if the template content changes (and those changes could be due to Solid templating updating the DOM)

trusktr avatar Jan 07 '24 06:01 trusktr