grych / drab

Remote controlled frontend framework for Phoenix.

Home Page:https://tg.pl/drab

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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!!