Many LiveComponents, inside of a live view - can't figure out submission events

Each component is a form for a different model, each component is stateful (at least I pass in an id to each.

One of them is a new model form instead of an edit form. So I naively pass a -1 as an id, perhaps that’s the issue. If that’s true, let me know and I’ll try to abstract out the form. Then I would use it for edit component (stateful) and new form component (probably need to be stateless).

Both if you think I’m doing this find already, with the stateful id:1 component. This is the render and the handle_event

  @impl true
  def handle_event("save", %{"player_test" => player_test_params}, socket) do
    IO.inspect("save")
    save_player_test(socket, socket.assigns.action, player_test_params)
  end

@impl true  
@spec render(any) :: Phoenix.LiveView.Rendered.t()
  def render(assigns) do
    changeset = Training.change_player_test(%PlayerTest{})
    players = LightSteel.Client.list_players()

    ~L"""
      <tr>

    <%= f = form_for changeset, "#",
      id: "test-player-form",
      phx_target: @myself,
      phx_change: "validate",
      phx_submit: "save" %>
        <td><%= select f, :player_id, Enum.map(players, &{&1.name, &1.id}) %></td>
        <td><%= number_input f, :result %></td>
        <td><%= textarea f, :notes %></td>
        <td><%= date_input f, :occured %></td>
        <td><%= error_tag f, :result %><%= error_tag f, :notes %><%= error_tag f, :occured %></td>
        <td><%= submit "Save", phx_disable_with: "Saving..." %></td>
    </form>
      </tr>
    """
  end

It doesn’t save though, and pressing the save button doesn’t seem to be caught by that handle_event call. Any ideas why?

1 Like

Hello, can you debug IO.inspect like this to show the return? :smile:

def handle_event("save", values, socket) do
    IO.inspect(values)
    save_player_test(socket, socket.assigns.action, player_test_params)
 end

You should only have an ~L inside render/1.
The variables you assign are not change tracked.

Also the f = assignment should be avoided according to the docs.

You probably don’t need a form and maybe submitting a form is the problem.
I haven’t tried submitting a form inside a LiveComponent.

1 Like

I should have mentioned that my IO.inspect that says ‘Save’ never gets called so not too worried about seeing the values.

1 Like

Could you point me where it says that?
As for the ~L being the only thing, that makes sense. Although, if it’s anything like react - it’s not that those aren’t being change tracked - the issue is they would be called too often, and in this case would DoS your db.

The docs are not consistent regarding variable assignment inside live templates.

This one says:

To sum up:

  1. Avoid passing block expressions to library and custom functions
  2. Never do anything on def render(assigns) besides rendering a template or invoking the ~L sigil
  3. Avoid defining local variables, except within for , case , and friends

And this one literally suggests defining a local variable just like you did:

<%= f = form_for @changeset, "#" %>
  <%= live_component @socket, SomeComponent, f: f %>
</form>

Only a few days ago I posted this question about the same subject.
I don’t know exactly what is the rationale or the right thing to do.

1 Like

I’ll keep an eye on your question see what comes :slight_smile: