Menkir

Menkir

Hi guys.
I’m currently working with the new LV JS API and it’s pretty cool. However i have a case where i need to trigger transitions of html elements from the server side. e.g.: A Notification that pops up after the last action was verified by the backend. Something that happens quite often.

I came up with a solution with a hook that triggers the transition by clicking on a hidden button.

Here a minimal example in surface:

LV template

...
<Notification id="notify-fail" 
type="error" 
title={@notitication} 
message={@message}/>

<Submit/>
...

LV callback

def handle_event("submit", params, socket) do
    socket = if valid?(params) do
         redirect(socket, to: "/foo")
    else
        socket 
        |> assign(title: "Something went wrong", message: "Pls check your foo")
        |> Notification.open("notify-fail")
    end
    {:noreply, socket}
end

Notification Component

defmodule Notification do
    use Surface.LiveComponent
    alias Phoenix.LiveView.JS

    prop message, :string
    prop title, :string

    def render(assigns) do
        ~F"""
            <div id={@id} class="..." :hook="Notification">
                <button id={@id <> "-trigger"} type="button" hidden :on-click={__MODULE__.show(@id)}></button>
               {!-- some template stuff  with @message and @string --}
            </div>
        """
    end

    # clientside open
    def show(id, js \\ %JS{}),
    do: JS.show(js, to: "##{id}", transition: {"ease-out duration-300", "opacity-0", "opacity-100"})

    # serverside open
    def open(socket, id) do
        socket |> push_event("open", %{id: id})
    end
    ...
end

Notification Hook

...
mounted() {
    this.handleEvent("open", ({id}) => {
        if(id == this.el.id){
            this.el.querySelector(`#${id}-trigger`).click()
        }
    })
}
...

Imo this solution seems like a dirty workaround because it created the necessity of writing an extra hook as well as providing two additional functions in the module doing basically the same thing . Will there be a feature handling this behaviour? Or do you know a better way of solving this issue?

greets

Showing Posts 1 to 3

riebeekn

riebeekn

I think hooks are currently the only option when wanting to call javascript from the server. I’d probably just put the necessary plain javascript in the hook however instead of going with the hidden button technique.

CherryPoppins

CherryPoppins

You can checkout Apline.js to handle stuff like this. I’ve found it works pretty good with typical controllers/templates, but in my experience it can be buggy in liveviews and I’ve only had limited success there before giving up on it. It’s been a few months though since i tried it out so maybe they have worked out some of the liveview issues where you seemingly lose your Alpine instance on DOM updates.

DecoyLexi

DecoyLexi

I had a similar problem and managed to solve it without using hooks. In addition to pushing events to hooks, LiveView also dispatches events sent with push_event/3 to the window with a phx: prefix.

live_helpers.ex:

def push_js(socket, js \\ %JS{}) do
  cmd = Jason.encode!(js.ops) # LiveView expects this to be a string when we call `execJS` on the client

  socket
  |> push_event("exec_js", %{id: socket.id, cmd: cmd})
end

app.js:

window.addEventListener("phx:exec_js", (e) => {
  let el = document.getElementById(e.detail.id)

  liveSocket.execJS(el, e.detail.cmd)
})

Then in your LiveView, you can just do

def open(socket, id) do  
  socket
  |> push_js(show(id))
end

There might be a better way to do this, but I haven’t found one yet.

— All posts loaded —

Where Next? Top

Trending in Questions Top

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
jonnycharles
I’m in search of an Elixir library that offers PDF generation capabilities similar to Ruby’s Prawn. While there have been discussions abo...
New
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
dli
Before I dive in myself, did anyone successfully sprinkle Hologram into their existing LiveView app? Looking for hints regarding: Addi...
New
roeland
Kia ora, We have been using elixir-google-api to connect to Google Drive. However, with the updates to Tesla due to CVEs this is now bro...
New
subsaharancoder
I’ve followed the Phoenix LiveView file upload code here Uploads — Phoenix LiveView v1.0.0-rc.7 and so far everything works just fine wit...
New
mohsen
I’m using an Umbrella project for a Phoenix application, and I want to have one Ecto Repo and one PostgreSQL database shared by all apps....
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
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
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
wintermeyer
There are three potential reasons for members of this forum to have a look at https://vutuv.de You are tired or annoyed of LinkedIn. Yo...
New

Latest on Elixir Forum

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews