How to create a modal

I’ve been online trying to learn how to create a Modal in Phoenix LiveView. I’ve been doing it for hours and I have no idea.

Do I create a LiveView and embed one LiveVIew into the other with one acting as the modal?

If so, how do I embed a LiveView into the other? I read the docs and they are not clear and direct. I used the example code and I have no desire to jump through another hour of errors just to embed a file into another.

Any direction I can be pointed in is useful.

I read that it can be done with JS here:
https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.JS.html

That doc doesn’t say how to build the Modal - just that you can. The rest of that text is a terse brick that requires a translator. I’m too dumb to understand it.

I’m sure it’s not that difficult.

As it stands I have a LiveVIew with a button and and when I click it, faux data is sent to the database. So that works.

I know how to write a form and submit the data to the database. I need to know what to focus on to complete the rest. When the user clicks the button, a form modal should appear. The form is filled out and submitted by a user. The data is captured and manipulated in the parent LiveView and sent off to the database.

Thanks

If you use the generator: mix phx.gen.live — Phoenix v1.7.0 it will create an example modal for you.

First decide whether you want your modal to hold state or just display values passed into it.

For example if your modal is going to contain a list of to do items you might want to go with a live component that can hold state.

If the modal is to let someone know that you have a newsletter, you could probably just go with a function component.

To get a nice looking modal without much work, you could try tailwind. Here’s an example.

Once tailwind is added to your Phoenix project you would just copy the code and paste it into your render function inside the H sigil.

The generator shows the code below. There is no documentation for it anywhere.

<.modal
  :if={@live_action in [:new, :edit]}
  id="user-modal"
  show
  on_cancel={JS.navigate(~p"/users")}
>

<.live_component
    module={AppxWeb.UserLive.FormComponent}
    id={@user.id || :new}
    title={@page_title}
    action={@live_action}
    user={@user}
    patch={~p"/users"}
  />
</.modal>

Other than the <.modal> tag, id and show attributes I don’t understand any of it.
The show attribute creates the pop up effect but I don’t know how to toggle it dynamically. The example is too complicated.

EDIT

I’m looking up socket.assigns.live_action

If I can understand that, I think the rest might be simple.

EDIT

Looks like socket.assigns.live_action isn’t in the documentation.

What you’re looking at is an imported Phoenix.Component <.modal ...> and Phoenix.LiveComponent <.live_component ...>.

I’d suggest reading the sections on attributes and slots on Phoenix.Component module docs and then searching for where the modal is defined in your project aka def modal.

Note that while the guide documentations are generally very good, they seem to often lag the module documentation since LiveView is still evolving rapidly.

2 Likes

I search the HEX docs for the word <.modal> multiple times thought I did’t see anything. Guess I was wrong.

You weren’t wrong, searching for <.modal> in the HEX docs would not have returned anything useful at the moment. There’s nothing really special about <.modal>, modal is just the name of a function in a module that got imported. If the module wasn’t imported, it’d look like <SomeModule.modal> or <SomeModule.some_other_function>.

Now if you had searched for .modal in the Phoenix repo itself, you may have found the phx.gen.live templates that add the modal function definition to your project.

3 Likes

With phoenix 1.7 a modal is created for you in core_components.ex. You could also try a simple css-only modal, look at daisyui for example.

Its easy to get that working with phoenix: How to get DaisyUI and Phoenix to work? - #19 by Sebb