jfpedroza

jfpedroza

Hi.

We are considering offering web components to our customers so they can embed parts of our application in their website. I’m exploring using LiveView for that and have found some challenges. I’m aware of LiveState and have tested it, but I want to rule out LiveView first.

I managed to embed a LiveView in another page in a web component without shadow DOM and have it connect to the socket, everything works.

Using web components without shadow DOM has the issue of component styles interfering with the global style and vice versa. So I want to make it work with shadow DOM.

The problem is that then the shadow root is not visible in the JavaScript side of LiveView since it looks up everything
starting from document. I managed to connect the socket and detected the live view by simulating what
liveSocket.connect() does.

component.shadowRoot.querySelectorAll('[data-phx-session]:not([data-phx-parent-id])').forEach(rootEl => {
  let view = window.liveSocket.newRootView(rootEl)
  view.setHref(window.liveSocket.getHref())
  view.join()
  if(rootEl.hasAttribute("data-phx-main")){ this.main = view }
});
window.liveSocket.bindTopLevelEvents()
window.liveSocket.socket.connect()

With that, I get the log that says phx-some-id mount: but then it fails in attachTrueDocEl because it tries to find
that ID in document. So, I think explicit support in LiveView is necessary to do this. Maybe keeping in each view
which root to use for lookup, whether document or some shadow root set during the “join” phase.

What do you think? Is that something that could be supported by LiveView? Or maybe there are other technical challenges that complicate things.

Showing Posts 1 to 10

kokolegorille

kokolegorille

Hello and welcome,

I have used web components with Phoenix socket and channels

It is simple because there is a npm phoenix package

https://www.npmjs.com/package/phoenix

It’s probably simpler than using Liveview socket, and can be used with shadow dom

jfpedroza

jfpedroza OP

Yeah, LiveState is based on that. I wanted to try to make Live View work since it allows the HTML to be handled by Live View templates and using the Phoenix components you already have. LiveState is basically LiveView without the rendering part.

johnknott

johnknott

I know you’ve seen live_state, just making sure you didn’t miss live_elements too by the same author.

jfpedroza

jfpedroza OP

I saw it, thanks. LiveElements is the opposite of what we want, though. LiveElements is for using web components inside a LiveView. We want a LiveView inside a web component.

adw632

adw632

I think you will need to fork the liveview package and patch it to work with a specified root. I don’t believe it would be a lot of work because essentially you are using shadowRoot instead of document.

You will need to consider how the websocket is managed, if you have multiple custom elements are they liveviews or live components? Perhaps you may need to model the liveview as a container custom element (which manages the socket) and within that you can use multiple live components also exposed as custom elements. Maybe you come up with a different abstraction.

You probably don’t want multiple websocket connections back to the same server for each custom element, especially if your custom elements can be modelled as live components within a LiveView on the Phoenix side.

The part I’m not convinced about is the double render that liveview requires to mount and render the initial html before the websocket is established and then the second mount and render occurs with the web socket. If your component is embedded in another web application how will the initial html be fetched and rendered?

jfpedroza

jfpedroza OP

What I did during my tests was expose an endpoint like you normally would for a LiveView and have the component use fetch on that endpoint and replace the HTML with the body of the response.

adw632

adw632

I guess you can do it that way, although it means the page load requires some more round trips before it can display content.

I do think there is a valid use case for this, Phoenix should be able to do SSR for custom elements using the draft Declarative Shadow DOM. I think conditionally rendering in the Heex templates within a template element in the initial render would support hydration of custom elements as per the spec.

I honestly don’t think there is much of a gap to build web components in Elixir with the initial render being regular LiveView and the component is delivered with some elixir transpilation to JS like what Hologram does and this could completely eliminate any need to run node to support server side Javascript rendering and provide a rich UI all in Elixir.

bob

bob

So, I usually just lurk here, but I think I was one of the first to figure out how to build and launch cross-domain LiveView widgets >3 years ago in a production application (fintech space).

The approach I took was a custom element that defined a shadow, and its contents were an iframe. Load your LiveView URL into the iframe. It’s as easy as that. If you need to also have client-side (from the embedding side) interactions, you’ll be using postMessage. Phoenix hooks between your LiveView and your server just work like normal. No hacking LiveView required (but it did lead to a coworker submitting a patch to Phoenix to fix up an issue with private browsing sessions that’s now included).

The CTO even gave a talk showing off my work at ElixirConf — https://youtu.be/DA32q8kd9pA?feature=shared

If I’m understanding what you’re looking for, I would be happy to chat with you more about it if you would like (email/zoom). There’s a number of little things to get right with CSP and whatnot to make the experience smooth and easy for those consuming your widgets/components. I can be reached at my username at my domain.

jfpedroza

jfpedroza OP

What you say about SSR, I’m not sure applies here, since the components would be embedded in third party pages. We don’t control where in the page the component will be.

I didn’t know about Hologram. Interesting project.

jfpedroza

jfpedroza OP

I agree that using iframe would remove all these issues since it provides an entirely different document.

I will watch that talk, thank you.

Where Next? Top

Trending in Questions Top

Blokh
Hey guys, I’ve got a huge CSV ( around 10 GB ) that needs to be processed hourly Do you guys have any suggestions what is the best prac...
New
kszambelanczyk
Hello! Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app. I creat...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New
psy-q
I’m trying to set up Emacs with elixir-ls via lsp-mode and credo via Flycheck. This should mostly be preconfigured as Flycheck picks up c...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews