How to pushEvent from javascript to LiveView

I am looking for a way to push an event from Javascript. In JavaScript interoperability — Phoenix LiveView v0.17.10 I can find pushEvent in specific lifecycle callbacks.

But how could I push arbitrary data to the server?

Thank you

Maybe this conversation and the library attached will be helpful?

I’m not entirely sure what you mean by “pushing arbitrary data,” but I’m guessing you mean something unrelated to a typical user interaction event like a click and so on; is that right?

2 Likes

When I needed this I did create a hook to relay events to LV. A little awkward, but I remeber asking here if there is a better solution and nothing came up. Would be nice, if you could just push an event from JS to LV.

Hooks.RelayHook = {
  mounted() {
    relay = this;
    document.addEventListener("relay-event", (e) =>
      relay.pushEvent(e.detail.event, e.detail.payload)
    );
  },
};

...

window.dispatchToLV = function (event, payload) {
  let relay_event = new CustomEvent("relay-event", {
    detail: { event: event, payload: payload },
  });
  document.dispatchEvent(relay_event);
};

You can use the main container of the LV for the hook-element.

<!-- live.hmtl.heex -->
<main class="container" phx-hook="RelayHook">
  ...
  <%= @inner_content %>
  ...
</main>
5 Likes

As mentioned above, live_json wraps this ability into a function:

import { sendData } from 'live_json';
sendData('your_handler', your_data); 
1 Like

Although it feels restrictive sometimes, organizing your javascript into a bunch of hooks, each corresponding to some element in the DOM, is a good thing. What do you mean by “push arbitrary data”? It has to be triggered by some event on some element, right? So you install event listeners at the mounted() callback, pointing to some methods within the same hook then you can pushEvent in your event listener.

When I did this I did not see a way to go the way you propose.
I needed to send updates to the server from a complex component written in JS.

You can dispatch a customEvent, embedded with whatever data you like, from anywhere in the js. In your hook, you can install an event listener in the mounted() call back to another method of the same hook. The customEvent will land in your hook method and you can pushEvent as usual.

I don’t get it. Isn’t that what I’m doing?

I was replying to this. If you already know how to do it then you can ignore my message. My point is: having to go through a hook is a good thing, for better code organization and also the tie in to the life cycle management of the liveview and the element of interest.