LiveView phx-change attribute does not emit event on input text

Hi everyone,

I was playing with phoenix liveView but I run into an issue. I have a form and want to validate each input text when the text change. So I added phx-change attribute on every input (I only have text, email and password field) but it does not emit any event when the text of any of my input field change. Strangely It emits an event when instead of phx-change I use phx-click. Am I adding the wrong attribute?
On React I used to add onChange={myCallback} attribute on text input, is there something similar? I checked phoenix_live_view.js doc but can’t find a solution. Could someone help me?

Today we require the phx-change to be on the parent form, not individual inputs

4 Likes

Thank you for the reply. Is this a design choice or it will probably be added in a near future?

At the moment I’m not planning on making it per input because you can get what you want with the form events, and every event will have all the form input so it’s generally a better approach.

1 Like

Doesn’t that mean you can’t quite as easily have composible form elements? Instead you’ll need to compose everything manually in code for each given form and all possible fields that it might dynamically have. In Drab I just use a drab child commander to add those and it is all very compartmentalized, so this would be a very useful feature in liveview.

I need to see concrete use cases first before settling on a broader API. Having the top-level form control its input is preferred because it’s generally what you want event wise, where a single change event provides the current client form state. More critically, it also allows us to more easily control the loading/disabled/patch states of form events where ad-hoc components make this more difficult, and open up race conditions to a programmer concern instead of library concern. For example, LV can lock the form or defer patches to the form before a server acknowledgement from the pushed form event, where ad-hoc inputs would not. So my current preference is to nail down the loading state and deferred patch handling at the form level and see if we need to go further from that base.

My initial thought is an autocomplete input, I want the input code to handle that, not the form itself as it doesn’t care, and adding that to every form’s handler just in the off chance the autocomplete version is used in the HTML is extra mental bandwidth to handle, plus however many other plugins the overall system will include over time. The autocomplete input is the precise use that I use a drab submodule for. In HTML all I have to do is craft an html element with special drab-* attributes and it auto-registers and hooks in the child commander, which uses the information in the attributes to know which autocomplete list to pull from (which can even push updates in real time without typing changes if the autocomplete list has backend changes). :slight_smile:

4 Likes

Why can’t you just use phx-keyup for individual form elements? That’s what I’m using and it works great.

You can, but you still have to tie it into the backend somehow, the frontend is not the issue. ^.^

1 Like

phx-keyup will pass the value of the input to the handle_event function which you can use to return the autocomplete options. Is that what you are trying to do?

Not me, I’m referencing putting in pre-built blocks into a page. For example, drab allows you to do something like <div drab-commander="MyCommander">...</div> and the div and everything in it is controlled by an entirely different commander (like a liveview socket) rather than the main one, allowing you to break up functionality and re-use it in a trivial manner.

Though perhaps you meant to reply to the OP rather than my post? ^.^;

1 Like

Oh!

I am trying to do exactly this in the future. But couldn’t you have a LiveView template conditionally render another template inside of it? Haven’t tried this yet but will be crossing this bridge soon.

You can conditionally render all you want as it is right now, but the backend functionality has to support everything you potentially want to do, whether actually using it or not, instead of allowing the system itself to manage it. It’s the main feature I’m waiting for liveview as my server design is integrally tied into the drab subcommander style of piecing things together (which I adore as it works really really well!), plus some other features like more fine-grained control of the page that liveview does not allow for yet without some really convoluted work-arounds that don’t fit even remotely easy, but is trivial in drab. ^.^;

1 Like

This is a massive bummer. I have a really, really big form with one country select in the middle. Based on the selected country, I want to display something differently. I do absolutely NOT want a phx-change on my form (massive amount of data on the wire (textareas with tens of thousands of words)), I just want a phx-submit. How do I detect the changes to just my country select? Doesn’t seem like I can nest forms either.

Hi @ryan-senn,

first of all, welcome to the Elixir Forum! I do have the same issue – I want finer-grained control. Right now, I abuse the phx-keyup in conjunction with phx-focus and phx-value to achive the desired function:

phx-focus will send the currently focused input element identified by the value in phx-value /some index). The value of the input field itself will be send on each keyup event.

See https://github.com/gutschilla/phoenix-liveview-todo-app/blob/master/lib/live_demo_web/views/page_view.ex for an example.

Thanks for your answer. I’ve read about a few other people (ab)using keyups to suit their needs.

The input that I want to listen to is a select and not a text input however (I assume no keyup?). I haven’t actually tried to dig deeper just yet, the app we’re developing won’t be released for another 2 months, making it a not so urgent situation.
I mainly wanted to share my use case to demonstrate that input level changes can be beneficial in some circumstances. I just intuitively assumed that it was an option, so it was quite a surprise to find out that it isn’t. Maybe because of previous experience with elm/react etc.

Thanks again for your example, it’s an interesting trick. I’m sure it will help out quite a few people searching how to do this!

2 Likes