Combining live validation and type-ahead/autocomplete in one LiveView form

Hi everyone!

How would I go about creating a phoenix LiveView form with a few input fields and live validation, and have one of those input fields have type-ahead/autocomplete functionality.
It seems like a bad idea to combine validation and this autocomplete functionality with one phx-change event. But I don’t think it’s possible to put a phx-change on one input field. Is this a case where nested forms would help? I’m new to LiveView, and I’m struggeling on how to combine the bits and pieces in this kind of situation.
I’ve used mix phx.gen.live for the form, so there is a validation in place.

Thanks for reading!

See this thread for a couple of ideas: Building a dynamic select component (in Phoenix LiveView?)

1 Like

This is not directly related to type ahead but more to the statement

When you’re handling the validate event, the params coming in will have a "_target" key with the name of the input that triggered the change. You can create multiple validate event handlers that match on different targets and handle them separately according to your needs.

A recent example comes to mind from live_beats upload_form_component.ex

2 Likes

Thanks! Seems like we’re dealing with a similar problem.

Wow, I totally missed that piece in the documentation. This is great though: now I can distinguish between changes more fine-grained, which is exactly what I wanted. Thanks!

1 Like

Not your fault, it’s basically not mentioned at all in the documentation except in LiveViewTest.render_change/2

If you need to pass any extra values or metadata, such as the “_target” parameter, you can do so by giving a map under the value argument.

I’ve ignored it and its significance, despite countless IO.inspects during debugging, until I saw it used in the live_beats code. :person_facepalming:

1 Like

I’m a bit surprised it’s so hard to find it in the docs. I could also find some more info here: Form bindings — Phoenix LiveView v0.17.7

When a phx-change event is sent to the server, the input tag and parent form tag receive the phx-change-loading css class, then the payload is pushed to the server with a "_target" param in the root payload containing the keyspace of the input name which triggered the change event.

I’ve got no idea what the word keyspace means btw :smiley:

Searching the docs for _target (Search — Phoenix LiveView v0.17.7) does not seem to work very well either. The above reference doesn’t show up.

That live_beats project is great to have as a reference, thanks again for the reference.

2 Likes

Thanks for the link to the form binding docs. I swear I looked for this info there and didn’t find any, :roll_eyes:

As far as I can tell, keyspace refers to the order of map keys to follow in the rest of the params to find the target change.

Following their example:

%{"_target" => ["user", "username"], "user" => %{"username" => "Name"}}

The target points to the top-level “user” key in the received params, and then to the “username” key in the nested map. So we can use it to pull out the change programmatically using the Access functions, instead of making various functions that match on different param shapes.

iex> params = %{"_target" => ["user", "username"], "user" => %{"username" => "Name"}}
iex> get_in(params, params["_target"])
"Name"
1 Like