How to Show the Rating Form

Learn how to perform event handling in stateful components.

Our rating form will display the form and manage its state, validating and saving the rating. We’ll need to pass a product and user for our relationships, and also the product’s index in the parent LiveView’s socket.assigns.products. We’ll use this index, later on, to update SurveyLive state efficiently.

Building the rating form component

The component will be stateful, and we’ll need to use update/2 to stash our rating and changeset in the socket. We create a new file, pento/lib/pento_web/rating_live/form_component.ex and define a component, PentoWeb.RatingLive.FormComponent. Then, we enter this update function:

Press + to interact
defmodule PentoWeb.RatingLive.FormComponent do
use PentoWeb, :live_component
alias Pento.Survey
alias Pento.Survey.Rating
def update(assigns, socket) do
{:ok,
socket
|> assign(assigns)
|> assign_rating()
|> assign_changeset()}
end
...
end

These reducer functions will add the necessary keys to our socket.assigns. They’ll drop in any assigns that our parent sends, add a new Rating struct, and finally establish a changeset for the new rating. Here’s a closer look at our “add rating” and “add changeset” reducers we add in pento/lib/pento_web/live/rating_live/form_component.ex:

Press + to interact
def assign_rating(%{assigns: %{user: user, product: product}} = socket) do
assign(socket, :rating, %Rating{user_id: user.id, product_id: product.id})
end
def assign_changeset(%{assigns: %{rating: rating}} = socket) do
assign(socket, :changeset, Survey.change_rating(rating))
end

There are no surprises here. One reducer builds a new rating, and the other uses the Survey context to build a changeset for that rating.

Now, on to rendering.

Rendering the component

With our socket established, we’re ready to render. As usual, we’ll ...