Supporting Web Components in LiveView

Nice just saw this post (you mentioned on Better interop with Javascript libraries (React, Svelte, etc.))

Anyway I agree with all your points, though I don’t even think you’d need point 3) about functional wrappers if this was done correctly.
Bullet points 1) and 2) are the important ones though.

Here’s some thoughts I had which may or may not be feasible but I’d love to see something like this:

Currently in HEEX you can do

<my-element some-prop={@some_prop} /> 

but not much else I think, and @some_prop gets converted into an HTML safe string.

I think if HEEX introduced

  1. some delimiter syntax that basically means “don’t turn this into a string but rather assign as an object (string, number, boolean, array or object, i.e. JSON-stringifiable data)”, such as some-prop=(@some_prop) (note the round brackets, but could be anything that’s different from ={@some_prop}, e.g. :={@some_prop}, =[@some_prop], ~{@some_prop}, etc.)
  2. an easy way of doing the equivalent of element.addEventListener("some-event", ...)

Then that’s really all you’d need.
A few examples of what it might look like, with

  • an array prop [1,2,3]
  • listening to a CustomEvent "appendNumber", with event.detail as a new number, which calls back to handle_event("append", num, socket):

All of these examples effectively do the equivalent of

const element = document.createElement("my-element"); element.numbers = [1,2,3]; element.addEventListener("appendNumber", (event) => lv.pushEvent("append", event.detail); 

Different ideas…

# Assumes you always send event.detail <my-element numbers=([1,2,3]) @appendNumber="append" /> # Specifies exactly what from the event object to take <my-element numbers=([1,2,3]) @appendNumber=({"append", "&1.detail"}) /> # side-note: that would also allow for more general events like clicks <div @click=({"click", "&1.clientX"}) /> # Use phx-xxx attributes like other functionality, also just sends all of event.detail <my-element numbers=([1,2,3]) phx-custom-event="appendNumber:append" /> # Use JS module <my-element numbers=([1,2,3]) phx-on-appendNumber={JS.push_event("append")} /> # As above but specifying what to take from event <my-element numbers=([1,2,3]) phx-on-appendNumber={JS.push_event("append", "&1.detail")} /> 

Anyway just throwing out a few ideas.

If that were possible, then:

  • Svelte, Vue, Angular, Solid can all easily compile to web components
  • Lit, Stencil etc. compile to web components
  • React components could be easily wrapped on a per-component basis (because mapping function callbacks → custom events would need to be done per-component)

and therefore would be even easier to integrate into a liveview app.

I don’t know how the HEEX compiler works (though am interested to look into it), so don’t know how feasible this would be, but I imagine it would mean the need for a Javascript script to be added after the whole page or something, and possibly the need for ids for that JS code to target the correct elements