silverdr

silverdr

I know I can have heex attributes like phx-click="eventid" in the markup and then

def handle_event("eventid", _, socket), do: [...]

But how does one send that event without actually interacting? There are some examples in the guides like:

yet they seem to cover different cases:

  • handle custom client-side JavaScript when an element is added, updated, or removed by the server
  • Triggering phx- form events with JavaScript

but what I need is best described as “triggering arbitrary event that can be handled with handle_event/3 with JavaScript”. I found something similar here:

yet it’s been some time and many Phoenix changes since that fine piece was written.

How would you approach this task today?

Showing Posts 1 to 8

cblavier

cblavier

You can send arbitrary events to your component from JS by using pushEvent : JavaScript interoperability — Phoenix LiveView v1.2.5

You just need to attach a Hook to your component and call pushEvent from there.

silverdr

silverdr OP

The hooks part of the guide says: “To handle custom client-side JavaScript when an element is added, updated, or removed by the server […]”. In my case there is no user interaction, no server “interaction”, nothing is mounted, added/removed nor updated. It’s just a JS callback function, which gets called by another piece of JS code. I’d like that JS callback to notify backend about the fact that it was called.

cblavier

cblavier

You need a hook attached to the live_component that will receive the events. This hook will be initialized on mount.

defmodule MyLiveComponent do
  def render(assigns) do
    ~H"""
    <div phx-hook="MyLiveComponentHook">
       ...
    </div>
    """
  end

  def handle_event("custom-event", _params, socket) do
    {:noreply, socket}
  end
end

Then in your hook, listen for custom JS events and propagate them to your LiveComponent.

export const MyLiveComponentHook = {
  mounted() {
    window.addEventListener("my-app:custom-event", => {
      this.pushEvent("custom-event", {})
    });
  }
}

You can now trigger JS events from wherever you want, they will be handled by the hook and propagated to your LiveComponent

const event = new Event('my-app:custom-event');
window.dispatchEvent(event);

I just wrote this code directly on the forum, I hope this is kind of working :man_shrugging:

LostKobrakai

LostKobrakai

One can also look at @cblavier’s answer from the bottom up.

You have something happening somewhere in your JS (your callback) and want it to notify a LV or LiveComponent. How would you tell whatever API you call where things should be routed to? There’s no module names or fixed IDs you could hardcode there. Your LV or component might even be present multiple times on the current page. So your best best is some form of PubSub, where producers of data don’t need to know consumers upfront. That’s the dispatchEvent part.

Now how do you consume those dispatched events in a way that the can be forwarded to your LV pieces/server. That’s where hooks come in. They connect some JS with a section of markup, which LV knows how to connect to things on the server. Hooks do receive LV lifecycle events that’s true, but that doesn’t mean all they do needs to be based on lifecycle events. You can also listen for any other things happening and react to those as well. That’s the addEventListener part.

So now the hook receives events. Then you can use pushEvent to push data forward to the server to handle in an handle_event callback.

silverdr

silverdr OP

Other than two small typos (missing set of empty parens and “addEventListeRner”) it does :smiley: thank you!

Yes, that’s a very good explanation, thank you!

What I think I was hoping for was something like for example phx-js="eventid" (form/syntax aside) and the rest would be already set, similar to how e. g. phx-click= and Co. is working but the way you explained it is fine too. I should probably push a PR updating the docs so that it is clear that not only “form events” and “lifecycle events” are effortlessly handled this way.

chrisdel101

chrisdel101

Sorry to necropost but I’m stuck w this issue. Both of these issues occur for me. I can receive from the server (on the client), but cannot push to the server.

  1. unknown hook found for..confHook
  2. LiveSocket.pushEvent is not a function
#server
 <div id="some-id" phx-hook="confHook" phx-click="select_user" phx-target={@myself}>HERE</div>

#client
let Hooks = {}
  Hooks.confHook = {
    mounted(){
      window.addEventListener("phx:show_confirm", e => {
        if (confirm("Are you sure you want to perform this action?")) {
            this.pushEvent("load-more", {})
              # User confirmed, perform the action
            } else {
              # User canceled
            }
      })
    },
  }
sodapopcan

sodapopcan

What does your app.js look like? Having only those errors as clues, they lead me to believe that you haven’t passed your hooks into your liveSocket constructor.

let liveSocket = new LiveSocket("/live", Socket, {
  params: {
    _csrf_token: csrfToken
  },
  hooks: Hooks # <-----------
 })

This isn’t done by default by mix phx.new, you have to do it manually.

If you’ve done this already then sorry!

chrisdel101

chrisdel101

Well I’ve deleted and discarded the non-working code now. But yeah, I was passing in the hooks like that.

— All posts loaded —

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
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
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
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
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
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
webofbits
Aludel - LLM Evaluation Workbench Aludel is an embeddable Phoenix LiveView dashboard for evaluating and comparing LLM prompts across mult...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews