How to create a form with a "Typeahead" style of adding association/embed using LiveView & LiveComponents

Evening, I’ve just run into a problem when playing round with a new LiveView form.

I’m looking to add associations to the form using a typeahead style interface. I start punching in a query and get a list of matches back, when I click it or use arrows keys & enter to select it my selection is added to the changeset and some additional fields based on my selection replaces the search box/results. The I can add another association below and repeat the process.

From a UX perspective I liked the search box being where the association is being added, rather than at the top of the form or off the side. For that reason I used a Live Component for each association that gets added to the changeset, which managed the query string and results internally.

The tricky bit is that I need a <form> for the search within the larger <form> and this seems to cause issues - the opening <form> tag for the search in the live component is being removed I think, and that search form would need a phx-change that targets the component to get the search results, but the phx-submit would need to target the component above it for adding the association to the changeset.

I’ve tied myself in knots thinking about this. Anyone done anything similar before with an example I could take a look at?

1 Like

I eventually worked out a solution, and having seen a few similar questions thought I’d post my solution below. It’s not perfect and a little fiddly due to the search input needing to be a part of the form changeset, but it’s workable for the time being.

The code is as I’m using it, so there’s some things that won’t be necessary, but the gist of it is handling search inputs in the phx-change event handler. Downsides include shared query and result state across the live_component (which now can be pretty much stateless even though I’ve not made that change yet) and the <datalist> doesn’t work as expected. I think some JS with a hook may resolve this but that’s a problem for another day.

Posted the code as a gist as the forum butchered the formatting.

The other solution would be to remove the search form from within the submitted form. This could be achieved with something like a modal (not the UX I’m after really), a side panel (again not the UX I’m after or suitable on mobile) or some clever JS to make it appear inline, even though it’s actually not (which kind of defeats the point of using LiveView).

I’ve got a lot more of this interface to build yet, and it’s only getting more complex so I’ll update with any changes as I make them.