Search code examples
hyperhtml

How to use hyperHTML.wire() with a string/number as id instead of an object?


I have an array of players: {id: string; name: string}[] that is updated by firebase when new players are available. This gives each time a NEW array of players with NEW player objects, but with the same id's.

Because I want to animate the elements when players are added/removed, I would like to reuse elements based on player.id.

AFAIK you can only pass an object to the wire function and not the player.id (string). Is there any way to achieve this?

const playerEls = players.map((p, i) => hyperHTML.wire(p.id)`<div class="player" style="${`transform: translateY(${i * 20}px);`}">${p.name}</div>`);

hyperHtml.bind(document.body)`<h1>Players</h1>${playerEls}`

Here you find a codepen to play with: https://codepen.io/jovdb/pen/rdOzvY

I've also tried to use hyperHTML.wire(p, ':player-' + p.id), but that recreates all elements.


Solution

  • please allow me to me bring you through the answer.

    you can only pass an object to the wire function and not the player.id (string)

    Your example is perfect to explain why primitives are not a good way to relate wired nodes.

    Imagine in that players.map((p, i) => ...) callback you use the i index, instead of p.id, or imagine any other part of the app would use a generic number.

    Objects are needed to grant uniqueness of the relation and you went very close indeed to the solution.

    I've also tried to us hyperHTML.wire(p, ':player-' + p.id), but that recreates all elements.

    If you think about it, the relation you have between a player and its live DOM representation is its container, which never changes, and is different from any other container that would represent different player info.

    const view = document.querySelector("section");
    hyperHTML.wire(view, `:player-${p.id}`)`...`
    

    There you go. As you can see in this fork of your Code Pen, now every player is unique per ID.

    I hope I've answered your question. Regards.