phoenixframework / phoenix_live_view

Rich, real-time user experiences with server-rendered HTML
https://hex.pm/packages/phoenix_live_view
MIT License
6.22k stars 931 forks source link

Unexpected DOM behavior on selecting an option within a select tag #1883

Closed kkalb closed 2 years ago

kkalb commented 2 years ago

Environment

Actual behavior

I came accross the behavior while updating my current project. When selecting an option from an HTML select the DOM seems to not be patched correctly. Since I was not sure if this behaviour occurs due to my other dependencies I created a new project following the Phoenix docs. Then I used the example from mix phx.gen.live to automatically generate everything which is necessary to create a new User. I changed the GUI in order that the age is not requested by a number input but a select with different options.

In the first screenshot you can see the form opened recently. As you can see none of the options is tagged "selected".

modal_just_opened

In the second screenshot I choose the option "18" by clicking on it. However the option is still not tagged "selected" as expected.

option_selected

When typing in some other field of the form the selected tag is set correctly.

form_updated_after_option_selected

Unfortunately, the selected tag is not updated when selecting another option.

another_option_selected

Expected behavior

Elixir version: 1.11.2 Phoenix version: 1.5.5 Phoenix LiveView: 0.15.4

Before updating my project the behavior looks like follows:

When a select is rendered recently, I expect the prompt to be selected right from the start:

modal_just_opened_expected

When selecting an option, I expect the option to be tagged "selected" accordingly.

option_selected_expected

When selecting another option the selected tag should update and be placed on the other option

another_option_selected_expected

josevalim commented 2 years ago

Hi @kkalb! Can you please start a new Phoenix project and let us know if you can reproduce the issue there, using latest LiveView? Thank you.

kkalb commented 2 years ago

Hey @josevalim! Thanks for fast reply.

We already reproduced this locally by changing everything to the latest version but did not document this. That's why we just created a new project and validated the behavior again by following Up and running and Phx.Gen.Live.

Versions printed by "mix hex.outdated":

Dependency Current Latest Status

The only code changes I made were adding following lines to the router

    live("/users", UserLive.Index, :index)
    live("/users/new", UserLive.Index, :new)
    live("/users/:id/edit", UserLive.Index, :edit)

    live("/users/:id", UserLive.Show, :show)
    live("/users/:id/show/edit", UserLive.Show, :edit)

and changing the example's input field to a select (in ./form_component.html.heex) by using following

    <%= label f, :age %>
    <%= select f, :age, ["18": 18, "19": 19, "20": 20] %>
    <%= error_tag f, :age %>

If you want, I can push all the code to a new repo.

rktjmp commented 2 years ago

For what its worth, I dont see selected="" change in Plain Old HTML, when using Firefox and Chrome on Linux. https://play.tailwindcss.com/d4WN5lJsQ2.

The selected="" attribute likely changes after typing in the LiveView because the changeset is getting updated and the selected tag is filtering out of that? When you alter the select directly, LV makes an effort not to alter the focused element which is why it's not patched in that case, at least that was my understanding.

kkalb commented 2 years ago

Well, for this issue it does not really matter if it is the "correct" behavior or not. It's completely different between 0.15.x and 0.17.x, where selected="" was for the 0.15.x version updated properly on validate() and after upgrading it does not anymore.

When we change the text input_field after selecting another value, it gets updated accordingly. On our production container, which is running with 0.15.x, we have a larger form with ~15 inputs, and the selected="" tag is updated directly after changing the dropdown value. However, on 0.17.x, it seems that we need to cycle through validate() again to send the correct selected="" tag to the client.

alexanderbaetz commented 2 years ago

Digging deeper on this behavior, @kkalb and I tried to simulate what @rktjmp was mentioning, i.e. to blur the select after an option was chosen by using a hook with an event listener. We've found out that as soon as the element is blured, the selected="" attribute is updated correctly. We are still unsure if this is intended since blur via a hook was not necessary as well as that a select seems to keep the focus even after choosing an option in the previous used version (Phoenix LiveView 0.15.x).

chrismccord commented 2 years ago

Can you verify if the correct selected item is sent to the server on change? As @rktjmp said, it may be a mismatch between the attribute and internal element property, but as long as what's sent to the server is the selected item reflected in the UI, this isn't an issue.

alexanderbaetz commented 2 years ago

Hey @chrismccord , we can verify that the selected item is sent correctly to the server on change. From this perspective, we can close the issue. Nevertheless, can you explain us why we have to blur the element using a hook in order to update the "selected" property correctly? We understand that focused elements are not updated by LiveView, but we don't understand why it was working before we updated to the newest version, i.e. setting the selected attribute correctly even if the element was still focused. Thank you in advance!

chrismccord commented 2 years ago

I honestly have no idea without doing a deep drive, but given that everything is working as expected from a data and end-user point of view, I consider this resolved. Thanks!