Skip to content
New issue

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

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

Already on GitHub? # to your account

Blur event prevents option_click #7

Closed
goblinJoel opened this issue Dec 30, 2022 · 9 comments
Closed

Blur event prevents option_click #7

goblinJoel opened this issue Dec 30, 2022 · 9 comments
Labels
bug Something isn't working

Comments

@goblinJoel
Copy link

goblinJoel commented Dec 30, 2022

I'm having trouble getting selections to work, and I've traced it to the blur event:

  def handle_event("blur", _params, socket) do
    {:noreply, assign(socket, :hide_dropdown, true)}
  end

For me, when I click on the option, the blur event fires, but the option_click and whatever is set on the form's phx-change never do. If I remove the :hide_dropdown assign, the option_click fires, and the form's change event happens.

I'm not entirely sure why it's blurring when I click an option, but it happens even if I use a live select with a minimal layout template and remove some other libraries from our app.js, so I don't think it's our own JS interfering.

I think this is probably a race condition where, if blur is processed before option click, the liveview updates with the hidden dropdown and drops the click event. Perhaps something could be done with send_update_after/4?

(Side note: I'm not sure the component template's phx_change: "change" on the text input itself goes anywhere.)

I'm thinking about what to do for a workaround in the meantime. This library seems very helpful to make a liveview-friendly select2 equivalent!

@maxmarcon maxmarcon added the bug Something isn't working label Jan 1, 2023
@maxmarcon
Copy link
Owner

maxmarcon commented Jan 1, 2023

Hi @goblinJoel and thanks for the bug report.

Just checking: you are using the latest version right? (0.3.1)

I tried to reproduce the bug in the showcase app but without success. If I click on an option in the dropdown, I see that the blur event fires first, followed by the option_click event. This is the expected behavior: clicking on one of the options in the dropdown is supposed to trigger the blur event, which removes the dropdown, but also the option_click event that causes the option to be selected. The end result (for me) is that the dropdown gets hidden and the option selected, and the form's change event is triggered.

Do you think you could create a repository that reproduces the bug you're seeing in your app? That would be really helpful!

(Side note: I'm not sure the component template's phx_change: "change" on the text input itself goes anywhere.)

This is necessary to avoid sending change events triggered by typing in the text input to the parent liveview. If you remove phx-change, when you type in the text input, your parent liveview will receive a change event, even though nothing was selected. It's basically rerouting all change events for the text input to the component, and the component will simply ignore them with a catchall handle_event callback.

@maxmarcon
Copy link
Owner

maxmarcon commented Jan 2, 2023

Ok I think I managed to reproduce it on an app I'm developing that uses live_select.

Whether the option click works or not seems to depend on what element lies behind the dropdown.

The first impression is that it doesn't work if there's another input element behind the dropdown, but I will have to confirm this, after which I will try to fix it.

@goblinJoel
Copy link
Author

goblinJoel commented Jan 2, 2023

Thanks for the reply! Glad you were able to reproduce it. I am indeed using it as a library. For what it's worth, I've been working on MacOS Chrome, in case browser version affects when or in what order events trigger. If I recall correctly, I also noticed that the html phx blur attribute appeared on the element in the dom before the change did -- not sure if that matters. Tomorrow, I could try the same app out in other Mac browsers.

Edit: If you find a workaround regarding what elements can/can't be behind the dropdown, that may be useful even if you don't find a quick fix.

Edit2: I just remembered something else related to using it as a library: I had some trouble getting it to work as a library, so at some point troubleshooting, I copied the non-minified JS hook code from the repo and used that for the hook rather than importing. (I forget which issue this fixed -- don't have the code in front of me today -- but the blur/change conflict remained.)

@goblinJoel
Copy link
Author

In addition to my edits on my comment yesterday, I tried a couple of things today:

  1. I reproduced this in Mac Firefox, so it's not just Mac Chrome.
  2. I cloned this repo and got the demo project to work (had to modify .tool-versions and use npm install because I don't have yarn). Using tailwind styling (which is what I'm using in my real project), it seems to work correctly. I can click the field, search for "new ", and click "New York City". The shell's debug logs show click, severl keydowns, blur, option_click, and change (in that order). The field now shows "New York City" in it.
    a. Switching to tags mode still works correctly. (Tags is what I need for my real project.)
    b. In both cases, phx-blur is in the dom on the element before phx-change, and the blur event logs before option_click, but it still works.
    c. I noticed that the form and input both have phx-change="change"
  3. I have a test page, which only loads app.css and app.js in the head and only has a div with the city search form in it (copied from this repo's readme). I used this the other day to try and eliminate conflicts from our project's layout or other files. I still get the issue, even though the only input on the page is the liveselect (and the hidden input it creates). Events logged are click, several keydowns, keyup, blur. Neither the component's nor the liveview's change events trigger.

Here's a gist with the relevant files/snippets for my test page: https://gist.github.com/goblinJoel/fa97c3b51f761a7d597e0f2f8ba6c3b4 . I am using :phoenix 1.6.15, :phoenix_live_view 0.18.3, and Elixir 1.14.2. This project is within a docker container, which shouldn't matter.

@maxmarcon
Copy link
Owner

I fixed it on master. I tested it on my app and it works. Can you please test it on yours against master?

Please do not copy and paste the hooks from the JS source.
Instead, as explained in the README, do this:

import LiveSelect from "live_select"

let liveSocket = new LiveSocket("/live", Socket, {
  params: {_csrf_token: csrfToken},
  hooks: LiveSelect
})

The fix for the issue consists in triggering option_click from a mousedown event and not from a click event. The mousedown event is processed before blur so the dropdown is still there when it fires.

Since one can't trigger a mousedown event from LV directly, I had to do it in the JS hooks. So it's crucial that you import the hooks in the correct way if you want the fix to take effect :)

Let me know if it works, then I'll release a new version.

@goblinJoel
Copy link
Author

goblinJoel commented Jan 3, 2023

@maxmarcon Yes, this works! I switched my dependency to the git link, main branch, rebuilt, and was able to get it to work. Thank you so much!

(It turns out the reason I couldn't get it to import previously and had to copy-paste was because I am not very good at JS and was doing it wrong! Had the same problem this time, but eventually figured out why hooks: LiveSelect and hooks: {foo, ...LiveSelect} worked but hooks: {foo, LiveSelect} didn't. The blur vs click issue was real though and is fixed by your update.)

@maxmarcon
Copy link
Owner

maxmarcon commented Jan 3, 2023

That's great! I'll release a new version right away.

Thanks again for reporting this bug and for the quick turnaround.

fixed by: c4618ba

@maxmarcon
Copy link
Owner

Version 0.3.2 released 👯‍♀️

@goblinJoel
Copy link
Author

Thanks for such a quick update!

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants