Sending "phx-value-index" with phx_change in select

Hi,

I want to send the index of the inputs_for during a phx_change event in a select input, like I have shown below,

<%= select(fa, :licensed_officially, binary_select_opts,
                  class: input_class,
                  name: "licensed_officially",
                  phx_change: "change_has_licensed",
                  "phx-value-index": fa.index
                ) %>

I tried to receive this in my handle_event like I have shown below, but no luck. Is this possible to do with select input? I know this is possible with button clicks?

@impl true
  def handle_event(
        "change_has_licensed",
        %{"licensed_officially" => licensed_officially_str},
        %{"index" => index},
        socket
      ) do```

phx-change should be binded on a <form> element, instead of a <input>, <select>, etc.

An example from official doc:

<.form let={f} for={@changeset} phx-change="validate" phx-submit="save">
  <%= label f, :username %>
  <%= text_input f, :username %>
  <%= error_tag f, :username %>

  <%= label f, :email %>
  <%= text_input f, :email %>
  <%= error_tag f, :email %>

  <%= submit "Save" %>
</.form>


Edit: not true any more. Ignore my answer.

phx-change support on inputs has been added by this commit.

Support for phx-change on individual inputs has been added at some point as well, which is described a few paragraphs later to where your documentation example came from.

1 Like
 <%= select(fa, :licensed_officially, binary_select_opts,
                  class: input_class,
                  name: "licensed_officially",
                  "phx-change": "change_has_licensed",
                  "phx-value-index": {fa.index}
                ) %>
@impl true
  def handle_event(
        "change_has_licensed",
        %{"licensed_officially" => licensed_officially_str},
        %{"index" => index},
        socket
      ) do

This still does not work, anything wrong that I am doing?

I’d imagine phx-value-… is not supported with phx-change events.

Oh! In that case is there any workaround to getting the index to the phx-change event?

Just to give a bit more info, I am trying to update some values on the changeset based on the index. For example - I have a list of “items” which are maps, and I want to edit few attributes of one of these items based on the index

I just saw this: You won’t get multiple maps. At best you’d get one map with both values in it. The callback is of arity-3: event-name, some metadata, socket.

You should be able to figure out which input is the source of the change event by inspecting the _target property passed by LiveView in the parameters (the second argument given to handle_event). That property contains the path to the input that triggered the change.

_target only shows which element. It does not give the index. This is a “Add one more” situation in a form. And based on a “select” input, I need to set a attribute in the changeset to nil, but to do that, need to figure out exactly which index I need to modify in the list since its a list of maps

These are the only two things thats passed,

%{"_target" => ["licensed_officially"], "licensed_officially" => "true"}

UPDATE:

I got the above result when I had the |name: “licensed_officially”| attribute in my form select. Once I removed it, I was able to get the index and a whole lot more information through the _target!

WEIRD

Well, it’s not so weird. The Phoenix.HTML.Form API is already setting the name attribute of the input, and that name is sent by LiveView as _target to your event handler (phoenix_live_view/phoenix_live_view.js at 8fb58099bf627d00f9ee405c565ccfb85af5c63e · phoenixframework/phoenix_live_view · GitHub). But because you were overrwriting the name attribute with “licensed_officially”, that’s what you were getting as _target.

The Form API is already filling the name property for you, in general there’s no need to override that behavior.

1 Like