DEV Community

Mykolas Mankevicius
Mykolas Mankevicius

Posted on

LiveView + WebComponents = 🚀

I really think LiveView is really amazing.
It has some interop with javascript.
But i think for the most cases the Hooks api is much to overkill.

You need to start managing ids and make sure there are no duplicates even for simple things.

Example a lazy loaded image to be replaced when loaded.

This is a gist of how the hook could look like:

And this is how you would need to use it:

<picture id={@id} alt={@alt} class={@class} style={"--preview-image: url(#{@preview})"} phx-hook="XImage">
  <%!-- truncated... --%>
  <img src={@image} alt={@alt} class="x-image" loading={@loading} />
</picture>
Enter fullscreen mode Exit fullscreen mode

Now it's easy to forget that you need to assign a unique id to a picture, but it's even harder to come up with unique ids for multiple images which are from a same entry. and we're not really using anything from the hook apart from the fact that we need some javascript.

Also the hook only starts working when the livesocket initializes.

So of course there is a better way, enter WebComponents.

and here's how you would use that:

<marko-image>
  <picture alt={@alt} class={@class} style={"--preview-image: url(#{@preview})"}>
    <%!-- truncated... --%>
    <img src={@image} alt={@alt} class="x-image" loading={@loading} />
  </picture>
</marko-image>
Enter fullscreen mode Exit fullscreen mode

And voila, you get the same functionality which starts working as soon as the browser registers the component, you don't need extra attributes to make it work, no ids/no phx-hook.

I've created menus/dropdowns/modals with webcomponents and it's much nicer as the webcomponents api is somewhat nicer to work with.

here's something maybe a bit more interesting a counter for an input:

<x-counter>
  <div class="flex items-center justify-between">
    <label class="flex justify-between">Counter</label>
    <p x-counter-value class="text-xs text-slate-500"></p>
  </div>
  <input type="text" id="counter" class="block w-full rounded-md border" />
</x-counter>
Enter fullscreen mode Exit fullscreen mode

Here's what it looks like:

and here's the code for the web-component:

When i have time i'll write about those components too!

Thank you and have a nice day.

Top comments (0)