Koszal

Koszal

Here is a simple component to show a modal dialog:

def modal_access(assigns) do
  ~H"""
  <.modal id="modal-access" class="phx-modal"}>
    <p>Request access to this tool?</p>
  </.modal>
  """
end

The modal is displayed after clicking a button.

  <button
    phx-click={show_modal("modal-access")}
    phx-data-tool-tag={@tool_tag}
  >

There are many tool buttons on the page and the user can click any of them.

This all works fine.

Now, inside the modal I would like to change

  <p>Request access to this tool?</p>

to

  <p>Request access to {@tool_name}?</p>

and this is where I get lost.

I did not think it was good idea to create multiple modals - one for each tool. (If I did that I could inject a different tool_name in the same loop that creates buttons.)

I was hoping I could let the server know which tool/button was clicked, then translate tool_tag to tool_name on the server side, and put it in the assigns (and then display (or update(?) the modal window).

How should I do it?

I have tried a few things, for example adding JS.push:

  phx-click={JS.push("did-select-modal") |> show_modal("modal-access")}

However, I don’t see any data reaching the server. (Plus I am not really sure how that should work - would I have to embed a live-view in the modal window?)

I am probably misunderstanding/missing some core concepts. Any guidance would be much appreciated!

K.

Showing Posts 1 to 3

Koszal

Koszal OP

I have stitched something together after a fair amount of head scratching.

  1. First, there is live_render, which allows instantiating a live view inside a functional component.

    <%= live_render(@conn, MyApp.ToolAccessModalDialogLive %>

    (Not really sure why the syntax is <%= ... %> rather than a usual component instantiation.)

  2. Now that I have a live view to send events to, I can use JS.push(...) However, I need to specify the target: JS.push(... target: ...) because the button that triggers showing of the modal dialog is outside that dialog.

  3. Using target: "modal-access" (see the snippet in my original question) does not work because "modal-access" is the id of the modal dialog, the actual live-view is nested inside.

  4. I specified the id in <%= live_render(@conn, .., id: ...) but that does not work either because the id gets overwritten with the auto-generated one.

  5. In the end I created a dummy <div id="receiver"> inside the live view and now I can JS.push events to that div. That works!

  6. The last problem was getting rid of the layout injected to the live_render-ed element. I ended up creating a new helper in MyAppWeb and then in my module I replaced

use MyAppWeb, :live_view

with

use MyAppWeb, :live_render

where live_render is like live_view but without the layout:

  def live_render do
    quote do
      use Phoenix.LiveView,
        layout: false

      unquote(html_helpers())
    end
  end

K.

sodapopcan

sodapopcan

Hey @Koszal!

Just to confirm, I take it you aren’t able to just make the whole page a LiveView? I feels a little heavy handed to have a LiveView just for managing modal data, but maybe not. Is there going to be more stuff than just the “Request access” message in them?

If you really need to get the data from the server, it may be better to sett up a JSON endpoint (again, assuming you must use with classic controllers).

There are ways to do this clientside as well and I’m happy to give you some ideas there if that’s an option.

A couple of other things:

  • The <%= ... %> syntax is used because live_render isn’t a component, it’s just a regular function call. A compont is a function that takes a single argument of assigns which you can see live_render is not.
  • Another way to remove the layout is to return a 3-tuple from mount/3 with the layout: false option:
    def mount(_params, _session, socket) do
      {:ok, socket, layout: false}
    end
    
Koszal

Koszal OP

just make the whole page a LiveView

Yes, I had come to the same conclusion as I was thinking this over!

The way I implemented it ended up particularly bad - the live view process starts running when the page loads even though it is possible that the user will never use the modal. There are already some elements on the page that could be live so turning the whole thing into a live view makes perfect sense.

(OTOH - since this is purely an exploration project - I would be curious to know how I could start the live view on demand - only after the ‘Show dialog’ button is clicked. That probably requires some JS trickery?)

live_render isn’t a component

Yes - I get it now. Both are functions but the signatures are different. To be a componet, the function must take assigns.

return a 3-tuple from mount/3 with the layout: false option:

Ah - indeed - mount! I knew I saw layout: false somewhere in the documentation…

Thank you very much for the pointers!

K.

— All posts loaded —

Where Next? Top

Trending in Questions Top

katta
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
achenet
Hello, I’m trying to build a basic Phoenix web-app, and I’d like to use Tailwind. However, when I launch mix phx.server, I get an error...
New
kpanic
Hi everyone, I am toying with the idea of building a “match maker” for giving personal help to people that wants to start coding. I sta...
New
Cxx-mlr
I’m working on a small exercise involving update_in/3, and I came up with this solution: data = %{ name: "Periodic Table", category:...
New
ChrisAmelia
I’ve got trouble wrapping my head around the order in which functions are called in this snippet (from Phoenix’s authentication): toke...
New
dillonoconnor
Is there any way to avoid the Hologram compiler running when using iex? It seems like the front-end code could potentially be disregarded...
New
thiagogsr
** (ArgumentError) expected :max_attempts to be a positive integer, got: {:@, [line: 10, column: 19], [{:max_attempts, [line: 10, column:...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
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
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
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

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews