Components
Modals
Modals
Modals sit on top of an applications main window and require a live view to handle their on/off state. We recommend using a new route to map to the on/off state.
Sizes
Router
scope "/", PetalProWeb do
pipe_through [:browser]
live "/", ExampleLive, :index
live "/modal", ExampleLive, :modal
end
Live view/component
defmodule ExampleLive do
use PetalProWeb, :live_view
# ...
@impl true
def handle_params(params, _uri, socket) do
{:noreply, socket}
end
# The modal component emits this event when `PetalComponents.Modal.hide_modal()` is called.
# This happens when the user clicks the dark background or the 'X'.
@impl true
def handle_event("close_modal", _, socket) do
# Go back to the :index live action
{:noreply, push_patch(socket, to: "/")}
end
# ...
end
HEEX template
<.a type="live_patch" to="/modal" label="Opens the modal" />
<%= if @live_action == :modal do %>
<.modal max_width="sm|md|lg|xl|2xl|full" title="Modal">
<.p>Content</.p>
<div class="flex justify-end">
<.button label="close" phx-click={PetalComponents.Modal.hide_modal()} />
</div>
</.modal>
<% end %>
Modal
3 guys are hiking through the woods when they find a lamp
One of them picks it up, rubs it, and out pops a Genie.
It booms "You have finally freed me after all these years, so I'll grant each one of you 3 wishes." The first guy immediately blurts out "I want a billion dollars." POOF, he's holding a printout that shows his account balance is now in fact 1,000,000,003.50
The second man thinks for a bit, then says "I want to be the richest man alive." POOF, he's holding papers showing his net worth is now well over 100 billion.
The third guy thinks even longer about his wish, then says "I want my left arm to rotate clockwise for the rest of my life." POOF, his arm starts rotating.
The Genie tells them it's time for their second wish.
First guy says: "I want to be married to the most beautiful woman on earth." POOF, a stunning beauty wraps herself around his arm.
Second guy says "I want to be good-looking and charismatic, so I can have every girl I want." POOF, his looks change and the first guy's wife immediately starts flirting with him.
Third guy says "I want my right arm to rotate counter-clockwise until I die." POOF, now both his arms are rotating, in opposite directions.
The genie tells them to think very carefully about their third wish. First guy does, and after a while says "I never want to become sick or injured, I want to stay healthy until I die." POOF, his complexion improves, his acne is gone and his knees don't bother him any more.
Second guy says "I never want to grow old. I want to stay 29 forever." POOF, he looks younger already.
Third guy smiles triumphantly and says "My last wish is for my head to nod back and forth." POOF, he's now nodding his head and still flailing his arms around.
The genie wishes them good luck, disappears, and the men soon go their separate ways.
Many years later they meet again and chat about how things have been going. First guy is ecstatic: "I've invested the money and multiplied it many times over, so me and my family will be among the richest of the rich pretty much forever. My wife is a freak in the sheets, and I've never gotten so much as a cold in all these years." Second guy smiles and says "Well, I built charities worldwide with a fraction of my wealth, I'm still the richest guy alive and also revered for my good deeds. I haven't aged a day since we last met, and yes, your wife is pretty wild in bed." Third guy walks in, flailing his arms around and nodding his head, and says:
"Guys, I think I messed up."
One of them picks it up, rubs it, and out pops a Genie.
It booms "You have finally freed me after all these years, so I'll grant each one of you 3 wishes." The first guy immediately blurts out "I want a billion dollars." POOF, he's holding a printout that shows his account balance is now in fact 1,000,000,003.50
The second man thinks for a bit, then says "I want to be the richest man alive." POOF, he's holding papers showing his net worth is now well over 100 billion.
The third guy thinks even longer about his wish, then says "I want my left arm to rotate clockwise for the rest of my life." POOF, his arm starts rotating.
The Genie tells them it's time for their second wish.
First guy says: "I want to be married to the most beautiful woman on earth." POOF, a stunning beauty wraps herself around his arm.
Second guy says "I want to be good-looking and charismatic, so I can have every girl I want." POOF, his looks change and the first guy's wife immediately starts flirting with him.
Third guy says "I want my right arm to rotate counter-clockwise until I die." POOF, now both his arms are rotating, in opposite directions.
The genie tells them to think very carefully about their third wish. First guy does, and after a while says "I never want to become sick or injured, I want to stay healthy until I die." POOF, his complexion improves, his acne is gone and his knees don't bother him any more.
Second guy says "I never want to grow old. I want to stay 29 forever." POOF, he looks younger already.
Third guy smiles triumphantly and says "My last wish is for my head to nod back and forth." POOF, he's now nodding his head and still flailing his arms around.
The genie wishes them good luck, disappears, and the men soon go their separate ways.
Many years later they meet again and chat about how things have been going. First guy is ecstatic: "I've invested the money and multiplied it many times over, so me and my family will be among the richest of the rich pretty much forever. My wife is a freak in the sheets, and I've never gotten so much as a cold in all these years." Second guy smiles and says "Well, I built charities worldwide with a fraction of my wealth, I'm still the richest guy alive and also revered for my good deeds. I haven't aged a day since we last met, and yes, your wife is pretty wild in bed." Third guy walks in, flailing his arms around and nodding his head, and says:
"Guys, I think I messed up."
Close modal target
If you’re nesting a modal inside a live component, the close event will go to the parent live view, instead of the component.
To fix this, you can change the target to be the live component:
<.modal title="Modal" close_modal_target={@myself}>
<.p>Content</.p>
</.modal>
Underneath the hood, this gets forwarded to the JS.push
function. Here’s what it looks like:
# in petal_components/modal.ex
JS.push(js, "close_modal", target: close_modal_target)
Properties
attr :id, :string, default: "modal", doc: "modal id"
attr :hide, :boolean, default: false, doc: "modal is hidden"
attr :title, :string, default: nil, doc: "modal title"
attr :close_modal_target, :string,
default: nil,
doc:
"close_modal_target allows you to target a specific live component for the close event to go to. eg: close_modal_target={@myself}"
attr :close_on_click_away, :boolean,
default: true,
doc: "whether the modal should close when a user clicks away"
attr :close_on_escape, :boolean,
default: true,
doc: "whether the modal should close when a user hits escape"
attr :hide_close_button, :boolean,
default: false,
doc: "whether or not the modal should have a close button in the header"
attr :on_cancel, JS,
default: JS.exec("data-cancel-default"),
doc:
"a JS function to execute when the modal is closed. Defaults to pushing close_modal event"
attr :max_width, :string,
default: "md",
values: ["sm", "md", "lg", "xl", "2xl", "full"],
doc: "modal max width"
attr :rest, :global
slot :inner_block, required: false