larshei

larshei

Pass custom/render-time data to LiveView client side hook

Hello beloved forum people!

I am currently looking for an option to have a LiveView JS Hook which I can pass custom data to, fully client side.

What do I want to achieve?

The idea is to have a “ScrollTo” hook which I can put on e.g. buttons and add a scroll target, then on click have the webpage scroll to that specific area.

To have the button reusable, it would be great to do something like

#... in ~H/render
<.button phx-hook="ScrollTo" scroll-target="main">To Top<button>
<.button phx-hook="ScrollTo" scroll-target="footer">To Bottom<button>

What I tried

I went through the docs but could not find an option to define custom data that is then available in the hook. This seemed to only be an option for push_event from the server. So I tried some random stuff, like addingdata="main" or phx-value-data="main" or phx:data="main", then inspected/console.log’d the event, but I could not find the custom data anywhere.

Question

Is there an option to pass custom, known at render,-time data to a client side hook?

Or should I maybe even generate a script section and generate the script on render?

Any ideas are welcome :slight_smile: Thanks!

Marked As Solved

codeanpeace

codeanpeace

If the payload’s only the dom selector, then you might not even need the detail option if you specify the to option and use event.target in the event handler.

window.addEventListener("scrollTo", event => event.target.scrollIntoView(true))

<button phx-click={JS.dispatch("scrollTo", to: "#main")}>To Top</button>

Also Liked

benlime

benlime

Although you found a kind of solution I’d like to add what I am doing when I need custom data in a hook.

There are two approaches which I found useful.

Use a data attribute and fetch it from the hook mount callback.

const Foo = {
  getBar() {
    // on string data
    return this.el.dataset.bar;
    
    // when using JSON data
    return this.el.dataset.bar && JSON.parse(this.el.dataset.bar);
  },
  mounted() {
    console.log('data from bar:', this.getBar());
  },
};
<.button phx-hook="Foo" data-foo="hello">Click Me</.button>
<.button phx-hook="Foo" data-foo={Jason.encode!(%{ bar: "world"})}>Click Me</.button>

I use that approach all the time if I want to process some data and the data is cheap to render inside the template.

Use pushEvent to send an init message and get the data via the reply.

const Foo = {
  mounted() {
    this.pushEvent('Foo:init', {}, (reply) => {
      if (reply.foo) {
        console.log("Got data for foo", reply.foo);
      }
    });
  },
};

In your LiveView:

<.button phx-hook="Foo">Click Me</.button>

def handle_event("Foo:init", _params, socket) do
  {:reply, %{foo: "bar"}, socket}
end

This approach is more suitable if you need to perform more complex tasks or have big payloads. For example I use this to initialize a rich text editor with a state stored in the db.

cmo

cmo

<button phx-click={JS.dispatch("click", to: ".nav")}>Click me!</butuon>

larshei

larshei

Uh, I like that! Thanks for the suggestion.

Side node if anyone stumbles over this later: At first I changed the event name "scrollTo" to "scroll" and got hundreds of errors in the browsers log, because "scroll" is an actual event that is fired when the user is scrolling :sweat_smile:

Where Next?

Popular in Questions Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
komlanvi
Hi everyone, I was playing with phoenix liveView but I run into an issue. I have a form and want to validate each input text when the te...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New

Other popular topics Top

KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 36820 110
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID&lt;0.412.0&gt; terminating ** (Postgrex.Error) FATAL...
New

We're in Beta

About us Mission Statement