WebReflection / hyperHTML

A Fast & Light Virtual DOM Alternative
ISC License
3.07k stars 112 forks source link

SVG elements in array not displaying #284

Closed danielmahal closed 5 years ago

danielmahal commented 5 years ago

Hi there!

I‘m having an issue when trying to render svg elements in hyperHTML in an array. Am I doing something wrong?

bind(document.body)`
  <svg viewBox='0 0 100 100'>
    <circle cx='5' cy='5' r='1'></circle>
    ${Array(100).fill().map((v, x) => (
      `<circle cx=${x} cy='5' r='1'></circle>`
    ))}
  </svg>
`

image

It is quite strange, because all the nodes shows up in the inspector correctly, but only the one that is outside the array is displayed. I‘m using the latest version (2.15.2) from https://npmcdn.com/hyperhtml/esm

When I try doing it without hyperHTML, it works as expected:

document.body.innerHTML = `
  <svg viewBox='0 0 100 100'>
    <rect cx='5' cy='5' r='1'></rect>
    ${Array(100).fill().map((v, x) => (
      `<circle cx=${x} cy='5' r='1'></circle>`
    )).join('')}
  </svg>
`

image

WebReflection commented 5 years ago

SVG nodes are special, if you don't create these from the SVG world these are just dumb elements with no special meaning.

The first node is part of the declaration so it's already an SVG node, the rest you inject must be created as SVG, not as Array of strings, resulting in just an innerHTML operation.

In few words, you need a wire, as shown in here: https://codepen.io/WebReflection/pen/wYZYoq?editors=0010

const {bind, wire} = hyperHTML;

const el = document.body;
bind(el)`
  <svg viewBox='0 0 100 100'>
    <circle cx='5' cy='5' r='1'></circle>
    ${Array(100).fill().map(
      (v, x) => wire(el, `svg:${x}`)`
      <circle cx=${x} cy='5' r='1'></circle>`
    )}
  </svg>`;

The way to tell a wire it's an SVG is to use svg as type, while the :id part makes the node uniquely related, in this case, to its parent container.