Is there any better way to pass assigns to the :action option?
Hi, first off thank you so much for this lib! I was especially attracted to it for built-in support for notification actions, which I was putting off implementing.
Unless I'm missing something, it's currently a bit of a chore to get data into an action button:
@impl true
def handle_info(...) do
url = ~p"/emails/#{email}"
action = create_link_button(url)
LiveToast.send_toast(
:info,
"Email \"#{email.subject}\" was processed successfully",
action: action
)
{:noreply, socket}
end
# have to wrap the :actions function with another function to pass state in
defp create_link_button(url) do
fn assigns ->
assigns = assign(assigns, :url, url)
~H"""
<.button phx-click={JS.patch(@url)} type="button" style={:secondary}>View</.button>
"""
end
end
Is there a better way to do this? Thanks!
Thank you, let me think of a good API change here to make this a little easier.
I'm down for API changes if you have a suggestion, but does something like this pattern better solve it?
opts = [
action: fn assigns ->
assigns
|> Map.put(:id, "123")
|> download_action()
end
]
LiveToast.send_toast(:info, "File parsed successfully.", opts)
attr :id, :string, required: true
def download_action(assigns) do
~H"""
<button
class="my-4 mr-4 text-sm font-medium bg-zinc-900 text-zinc-100 px-2 py-1 rounded-md hover:bg-zinc-800 hover:text-zinc-200"
phx-click="download"
phx-value-id={@id}
>
Download Item <%= @id %>
</button>
"""
end
If I had to resuse that more than once I'd probably also make a helper function like:
def send_download_toast(download_id) do
opts = [
action: fn assigns ->
assigns
|> Map.put(:id, "123")
|> download_action()
end
]
LiveToast.send_toast(:info, "File parsed successfully.", opts)
end
and reuse it if it was needed.
That being said I am down to change the API for this customization if you have a suggestion. It's just kind of a hard problem. I think passing a function is the write move though because you can do stuff like this where you just edit the assigns.
Also if this pattern is satisfying, we can put it in the docs.
Yeah, I agree that those examples would be perfect- it took me a minute to grok my current solution and that looks cleaner.
One other idea- would it be too heavy or messy for send_toast's options to have an assigns that's merged in and passed to any action or custom notification component?
Eg.
def send_download_toast(download_id) do
opts = [
action: &link_button/1,
assigns: [url: ~p"/files/avatar.png", icon: "hero-download"]
]
LiveToast.send_toast(:info, "File parsed successfully.", opts)
end
My only issue with the current solutions is that wrapping the action / custom component in a lambda isn't as intuitive for me. But I could definitely be over-complicating this.
If this feels too complicated, I think the alternative is just for me to make my own helper in my codebase that takes assigns and action and returns a new action.
I think passing the assigns would not be a great default, but I could be persuaded otherwise if there was something you couldn't accomplish by building the lambda. I understand it may be a little counterintuitive though.
That's fair, the workarounds are fine. I can take a stab at a PR to add docs for them if you'd like.
Sure, it would be appreciated!
Hello @dfalling, sorry we didn't merge your PR earlier, I've had a lot of other things I've been working on. I'm still interested in getting an example along the lines of what you have here but I'm not sure exactly what it should look like. It is kind of an elixir question more than one concerning this library exactly.
I'm not sure myself if it really needs its own section, or more so just some kind of explanation at the places where we detail the various options what kind of parameters the action callback takes, you know what I mean?
Hey @srcrip, no worries! I had originally asked because while it's very Elixir-y to make a closure to capture some data, it wasn't my first thought for a callback from a notification. I thought I'd pass some data to the notification which would be passed on to the component in the assigns.
Definitely not a problem now that I know, but it felt like something that might trip up other people as well.
Thank you for the clarification!