Reputation: 11743
I have a Phoenix LiveView with a form that is not backed by a data layer, like so:
<%= f = form_for :post, "#", [phx_submit: :create_post %>
<%= textarea f, :message, placeholder: "Say something:" %>
<%= hidden_input f, :user_id, value: @current_user.account_id %>
<%= submit "Post" %>
</form>
I can't back the form with a changeset because I am not using Ecto. After submitting the form, the submission is processed just fine, but the form textarea
is not cleared. How can I clear inputs without resorting to Javascript?
If I can't do it without Javascript, how can I do it with Javascript, but without bypassing the LiveView phx-submit
mechanisms?
Some additional troubleshooting information:
Here is my event handler:
def handle_event("create_post", %{"post" => post_params}, socket) do
thread_id = socket.assigns.thread.id
user_id = post_params["user_id"]
posts = Forums.append_post!(thread_id, user_id, post_params)
UdsWeb.Endpoint.broadcast_from(self(), build_topic(thread_id), "new_post", %{posts: posts})
{:noreply, assign(socket, :posts, posts)}
end
I've tried several different approaches to fix the problem, mostly involving variations of data structures backing the form.
Phoenix.HTML.FormData
protocol, and Phoenix only implements this for Plug.Conn
and Atom
Conn
to use in my form, because this is a LiveView, but I could create a Conn
in the LiveView controller, so I did. I backed the form with it and passed a new instance through in the event handler for post creation. This did not solve the problem.textarea
to a text_input
, and this input cleared immediately on submission of the form. So it seems the problem is specific to the textarea
element. I'm not sure whether or not this is a bug with Phoenix.Upvotes: 4
Views: 2142
Reputation: 6373
Even it behaves like a SPA it is not a SPA, so you still need to use the backend router and redirect it back to the index
page. Your form is on the index
page but the resource is not the post's index
page, it is post/new
.
So, you need to use push_redirect
(not redirect
):
|> push_redirect(to: UdsWeb.post_index_path(socket, :index))
def handle_event("create_post", %{"post" => post_params}, socket) do
thread_id = socket.assigns.thread.id
user_id = post_params["user_id"]
posts = Forums.append_post!(thread_id, user_id, post_params)
UdsWeb.Endpoint.broadcast_from(self(), build_topic(thread_id), "new_post", %{posts: posts})
{:noreply,
socket
|> push_redirect(to: UdsWeb.post_index_path(socket, :index))}
end
Hex: https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.html#push_redirect/2
Upvotes: 1
Reputation: 1160
As Aleksei said in his comment: You have to pass a new Post
struct from your controller to your view. For example like this:
def handle_event("create_post", post, socket) do
# Here do what you want with the data from the "post" parameter
{:noreply, assign(socket, :post, %Post{})}
end
Upvotes: 2