coen.bakker
I was trying out a pattern I haven’t tried before: sending a message from a regular API controller to a LiveView process.
See code below for some of the relevant code. In a nutshell. One route for LiveView showing a registration form. One route for handling POST requests from that form. On form submit an AJAX POST request is made from the LiveView. In case there are any validation errors the form controller tries to send a message to the LiveView. At this point that message is just a non-sense test message. The LiveView does not receive the message, however.
# Router
live "/form", FormLive
post "/form", FormController, :create
# PageLive
<script>
function handleSubmit(event) {
event.preventDefault()
const form = event.srcElement
const formdata = new FormData(form)
const ajax = new XMLHttpRequest()
ajax.open("POST", "/form", true)
const crsfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
ajax.setRequestHeader('x-csrf-token', crsfToken)
ajax.send(formdata)
}
</script>
def handle_info(:hello, socket) do
IO.puts "RECEIVED" # Does not print after controller has sent the message
{:noreply, socket}
end
# RouteController
# one or several validation errors
%{"sender_pid" => sender_pid} = changeset.params
IO.inspect sender_pid # "#PID<0.2900.0>" Note: String
pid = String.slice(sender_pid, 5..-2)
pid = pid(pid) |> IO.inspect # #PID<0.2900.0>
send(pid, :hello)
conn
|> Plug.Conn.resp(406, "Not all form requirements have been met.")
|> Plug.Conn.send_resp()
I hope this code provides sufficient context for my question: It seems I can’t send messages from my controller to the LiveView, why is that? I reckon I can use PubSub to get the job done, but I prefer to understand why the pattern I’m trying doesn’t work. I looked around in docs etc., but haven’t found a definite answer, yet.
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixirconf-us
- #ai
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #hex
- #security










Showing Posts 1 to 10- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
al2o3cr
What does
Process.info(pid)return?Can you show where
sender_pidis captured? I’m not sure what other processes it could be picking up (a Cowboy acceptor maybe?) but it would explain what’s happening.benwilson512
As a design question, can you elaborate on why you’re doing it this way instead of submitting the form into the live view process itself? This seems like a much more complicated way of achieving
phx-submit.trisolaran
I would also question the design choice
. But, putting this aside, where does your controller get the pid of the LV process from? Your code seems to suggest that the pid is sent as part of the form submit. If so, how does it work? It could be you’re just sending the message to the wrong pid.
coen.bakker
The idea is this. LiveView form for registering users. Because it is a user register, and I need to set cookies, I must use a regular controller, not a LiveView, when submitting the form. However, I use a
phx-changeon the form to check for validation errors as the user is filling out the form.When the user submits an invalid form, the controller handles it. Plug.Conn requires a response being sent back to the client, but I don’t want the page to reload, because it isn’t necessary. The current page just needs to be send some info about the errors. So I don’t
render()orredirect()inside the controller in case of validation errors and I try to send amessageto the LiveView process.I have made some adjustments to the code. I was sending the
pidas a string as part of the form data before. The controller then reconstructed apidfrom that string. That was just a temporary solution. Now the LiveView registersself()under a name and the controller uses that name to get the right pid-address to send the message to.Message to LiveView still does not get handled by
handle_info.Here the current code with returns of
IO.inspectin comments. So this is the actual code, so names are different from original post.So this is the behaviour.
cmo
Is it really that big of a deal to do a redirect after registering? Don’t you want to update the session and change the page, or are you planning to keep them on the registration page once they’ve registered? Or are you doing it just in case there is an error and you want to display that in the liveview? If that’s the case, why don’t you register the user in the liveview, display the error in case of error or redirect if successful.
LostKobrakai
I’d suggest taking a look at
trigger-action. It allows LV form handling to trigger a POST request once the form is validated, up until that everything is handled as normal using just the LV.coen.bakker
Well, it isn’t a big deal to have the page reload. I sometimes go out of my way to try something new/different, to be able to learn from the experience. If there is a reason messages cannot, or should not, be sent from a controller to a LiveView, I prefer to know why.
derek-zhou
You can send message from anywhere to anywhere. Most likely you didn’t have the right pid. No one knows the pid except the LV process itself and its supervisor. How did you get the info to the controller?
coen.bakker
If registration was successful, the user is redirected (or that’s the plan at least). If registration is not successful, they stay in the LiveView. I could rerender the LiveView if registration failed and pass the changeset returned by the failed registration. That’s how I handled it before trying to send a message from the controller to the LiveView instead.
Just use a LiveView for the registration form? I was told that the registration page can be rendered as a LiveView, but that the registration cannot be handled by a LiveView. Since LiveViews cannot set the auth token cookies.
coen.bakker
Thank you! That’s good to know.
Must have overlooked something then. I could have sworn it is the same PID, but then I know it makes sense to keep debugging.