Does anybody knows why this does not work at all?
When I click LAZY it tries to submit the form (it cant because there is no handle_event to handle it which is correct). But why it cant by clicking Publish have the same effect since JS is supose to perform a click on LAZY button?
defmodule JsformWeb.HomeLive do
use JsformWeb, :live_view
alias Phoenix.LiveView.JS
def mount(_p, _s, socket) do
changeset = %Ecto.Changeset{}
{:ok, assign(socket, changeset: changeset)}
end
def render(assigns) do
~H"""
<div>
<.form let={f} for={@changeset} as="something" phx-submit="add-add">
<%= submit gettext("LAZY"), id: "submit_button" %>
<button type="button" phx-click={JS.dispatch("click", to: "#submit_button")}>
Publish
</button>
</.form>
</div>
"""
end
end
Sending a click CustomEvent (which is what JS.dispatch is doing in the background) doesn’t trigger the lazy button’s own click handler to submit the button, you have to do that yourself.
You can either add an event listener on the submit button, kind of like the example code in the docs
let lazy = document.getElementById("submit_button")
lazy.addEventListener("click", e => e.target.click())
Or catch the click on the lazy button and dispatch the submit to the form in idiomatic LiveView.JS
def render(assigns) do
~H"""
<div>
<.form for={@changeset} as="something" phx-submit="add-add" id="some_form">
<%= submit "LAZY", id: "submit_button",
phx_click: JS.dispatch("submit", to: "#some_form") %>
<button type="button"
phx-click={JS.dispatch("click", to: "#submit_button")}>
Publish
</button>
</.form>
</div>
"""
end
Or just dispatch the form submit directly on the Publish button.
God yes, sorry. I was checking to see if that still submitted itself when clicked or if you had to have an actual type of submit or something. Then hurt myself in confusion.
The reason why I’ need to do this is because I need to set an “state” just before I press the submit.
My case is that I have a kind of complex form with a SAVE and PUBLISH button. the problem is that you cannot have 2 submit buttons in a form and see which did one you clicked so you can have some logic when to SAVE or PUBLISH.
In my case what I wanted to do so solve this issue… was to have:
1 hidden text field, that stores the action performed
1 real submit button that is hidden
1 fake submit PUBLISH button
1 fake submit SAVE button
when you click fake SAVE, it triggers the phx-cli and calls JS.set_attribute on the hidden text field with “save” and do a JS.dispatch(“click”) on the hidden submit form
when you click fake PUBLISH, it triggers the phx-cli and calls JS.set_attribute on the hidden text field with “publish” and do a JS.dispatch(“click”) on the hidden submit form
My problem is that it does not “click” the “submit”
Can you not track the form state via phx-change, then have <button type="button" phx-click="save_draft"/> and have that just save the current state?
Be careful, as JS.set_attribute wont over-write values, so if someone hit “save draft” then “publish”, you may still see the action as “save draft”. You have to chain JS.remove_attribute into set_attribute.
def set_action(action \\ "save") do
JS.remove_attribute("value", to: "#action") |> JS.set_attribute({"value", action}, to: "#action") |> JS.dispatch("submit", to: "#form-create-planner")
end
There is an issue in chrome where node.dispatchEvent(new Event("click")) does not do the same thing as node.click(). Currently JS.dispatch does not special case anything, as it literally only calls dispatchEvent on The DOM apis. I may considering special casing click, but you can also add an event listener on the click and do this yourself, for example:
# phx-click={click("#foo")}
def click(to) do
JS.dispatch("my:click", %{to: to})
end