Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can I handle input changes myself #54

Open
Papipo opened this issue Jan 7, 2024 · 14 comments
Open

How can I handle input changes myself #54

Papipo opened this issue Jan 7, 2024 · 14 comments

Comments

@Papipo
Copy link

Papipo commented Jan 7, 2024

Hi!

First of all, thanks a lot for your work, it's great!

I wanted to create a dynamic hierarchical LiveComponent wrapping LiveSelect. The problem I have is that when an option is selected, it's the Root LiveView (through the form's phx-change) who gets the even.

I tried wrapping the Heex in another form tag but that didn't work. I don't know if there is any other way of having more control over who gets the change event.

There might be an obvious way but I am new to LiveView, sorry.

Thanks in advance,
Rodrigo.

@Papipo
Copy link
Author

Papipo commented Jan 7, 2024

I think a workaround could be to support a form_owner attr

That way I can just wrap my live selects in a nested form tag that owns them.

@maxmarcon
Copy link
Owner

Hi @Papipo. You simply have to add the phx-target attribute, as explaned here. Hope it helps.

@Papipo
Copy link
Author

Papipo commented Jan 8, 2024

Hi @Papipo. You simply have to add the phx-target attribute, as explaned here. Hope it helps.

I don't think it does because for validation and saving I still need the parent LV to handle the phx-change.
I mean, I handle live_select_change on my LiveComponent without issues. The field change-ing is what is problematic.

@maxmarcon
Copy link
Owner

It should work. You have to add the phx-target assign to your form component as well. Double check please.

@Papipo
Copy link
Author

Papipo commented Jan 8, 2024

I haven't been able yet to fix this. The best solution has been to use send_update from the grandparent liveview (LV -> My Live component wrapper -> LiveSelect is the hierarchy here). To aid on this, I added a __using__ macro to define a handle_event in the LV easily. But it feels white hacky. I think my issue is exactly like this one: https://elixirforum.com/t/liveview-pattern-how-a-live-component-rendered-inside-a-form-should-handle-its-own-internal-form-inputs/44409/5

Still, I think that it might make sense to use a JS hook on my LiveComponent but I'm not sure if there is a way to stop form change events to propagate from the form inputs.

@maxmarcon
Copy link
Owner

Really hard to help you without seeing any code. Maybe you can share something?

@Papipo
Copy link
Author

Papipo commented Jan 8, 2024

I have invited you to a poc repo which has the same setup and the same issue

@maxmarcon
Copy link
Owner

Thanks. I've taken a look. First of all, for your information, nested forms are not valid HTML. They're simply not allowed.

Now, I don't know exactly what your hierarchical live select is supposed to be doing, maybe you can explain the idea behind it so I can suggest some design options?

My guess is that your component is supposed to contain one or multiple live select elements and "intercept" change events from the live select inputs, so that they're handled in the component and not in the parent form's change event handlers. Is this correct?

In this case, in LV, you can achieve this by using custom phx-change and phx-target on the input element (https://hexdocs.pm/phoenix_live_view/form-bindings.html#form-events).

However, live select currently doesn't support this. I could add it though.

Let me know.

@Papipo
Copy link
Author

Papipo commented Jan 8, 2024

Yes, that is what I think I need, to intercept the event when an option is chosen without it bubbling up to the form. Thanks and sorry for the poor explanation.

@maxmarcon
Copy link
Owner

Ok, then I can add support for custom phx-change / phx-target attributes to live select. I don't know exactly when I'll find the time for it though, it's kind of a busy period for me. But I'll keep this in the back of my mind, promised.

You are of course welcome to contribute a PR if you want to!

@Papipo
Copy link
Author

Papipo commented Jan 8, 2024

I can try, apart from supporting the assigns I guess this is mostly js stuff?

@maxmarcon
Copy link
Owner

I believe there's no need for changes in the js hook. It should be enough to replicate the assigns in the hidden input elements that are used to contain the value of the selection.

@Papipo
Copy link
Author

Papipo commented Jan 12, 2024

Hey @maxmarcon I have this working locally. We need two new assigns:

  • selection_event: Event to be fired when an option is selected. This will prevent a change event bubbling up to the <form>.
  • selection_target: If you have a LV -> LiveComponent -> LiveSelect, you might want to get the selection event in the LiveComponent (that's my use case), so you can pass selection_target={@myself}. Otherwise, the LV will get it. This assign is useless without selection_event.

This is how I have called them, let me know if you'd rather use other names and if you agree with the approach.

BTW, I saw that you are using hidden inputs because there were issues with select fields but I think that's no longer the case.

@maxmarcon
Copy link
Owner

Hey @Papipo and sorry for the late reply.

Why do we need a new selection_target assign? LiveSelect already supports phx-target and we can use that one as far as I can see.

For selection_event, in order to remain consistent with LV conventions, I would simply use phx-change. That's the only new assign we need.

Please share your code or create a PR, so we can have a more meaningful conversation about this :)

thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants