Koszal
Parametrizing my first modal dialog
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.
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #elixirconf-us
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #hex
- #performance











First 3 of 3 Posts
Koszal
I have stitched something together after a fair amount of head scratching.
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.)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.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.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.In the end I created a dummy
<div id="receiver">inside the live view and now I canJS.pushevents to that div. That works!The last problem was getting rid of the layout injected to the live_render-ed element. I ended up creating a new helper in
MyAppWeband then in my module I replacedwith
where
live_renderis likelive_viewbut without the layout:K.
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:
<%= ... %>syntax is used becauselive_renderisn’t a component, it’s just a regular function call. A compont is a function that takes a single argument ofassignswhich you can seelive_renderis not.mount/3with thelayout: falseoption:Koszal
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?)
Yes - I get it now. Both are functions but the signatures are different. To be a componet, the function must take
assigns.Ah - indeed -
mount! I knew I sawlayout: falsesomewhere in the documentation…Thank you very much for the pointers!
K.