updatable/interactive Drab.Modal, how to?
guidotripaldi opened this issue · comments
I would like to add some interactivity to a Drab.Modal box, i.e. be able to update its body content when the user acts on its controls.
Of course it is not possible to use Drab.Live.poke
directly because the body is not rendered the standard way, but instead it is possible to use Drab.Element.set_html
to change the content of a specific <div>
in the body.
The main problem concern is on which is the right way to trigger the event when an input control is clicked/changed. onclick="Drab.exec_elixir('MyApp.MyCommander.my_function', {})"
works well, but when it is used in form input elements like in
<%= select(:form, :item, 1..3, onchange="Drab.exec_elixir('MyApp.MyCommander.my_function',{})")%>
the triggered functions doesn't receive the changed value of the select
tag. To retrieve the value it should be used the usual form
<%= select(:form, :item, 1..3, drab: "change:MyApp.MyCommander.my_function()")%>
,
but it doesn't trigger the function. Actually it triggers it, but only after updating the body through Drab.Element.set_html
.
So, given that Modals aren't yet oficially "drabbable", which is the best way to approach the problem?
The following toy code show a Drab.Modal box (bootstrap4) with two <div>
, one button
, and one select
tag.
The button
triggers through Drab.exec_elixir
, while the select
tag tries to trigger through drab="change:.."
and it works only after the body is updated by clicking the button.
The Commander:
defmodule MyApp.TestCommander do
use Drab.Commander, modules: [Drab.Modal]
...
defhandler show_modal(socket, sender) do
title = "TEST"
time = Time.utc_now |> Time.to_string
body = render_to_string("_custom_body.html", time: time)
buttons = [cancel: "Cancel", ok: "OK"]
alert(socket, title, body, buttons: buttons)
end
defhandler test_update(socket, parameters) do
set_html(socket, "#my_time", Time.utc_now |> Time.to_string)
set_html(socket, "#my_sender", "#{parameters["sender"]}")
end
defhandler test_update(socket, sender, parameters) do
set_html(socket, "#my_sender", "#{parameters["sender"]}, value: #{sender["value"]}")
end
...
The custom body templates/test/_custom_body.html.drab
:
Time:
<div id="my_time"><%= @time %></div>
<br>
Sender:
<div id="my_sender">-</div>
<br>
<button type="button" class="btn btn-sm btn-primary z-depth-0" onclick="Drab.exec_elixir('MyApp.TestCommander.test_update', {sender: 'button'})">Update</button>
<%= select(:form, :item, 1..3, drab: "change:MyApp.TestCommander.test_update({sender: 'menu'})")%>
Hi Guido, I will take a look on this over the weekend.
Hi Guido,
could you please check the current master?
Yes, it works great!!