Problem using the same value on a re-rendered "modal" livecomponent

Hi,
I am facing an issue with a modal dialog that is shown conditionally with a css class. I use an assign to toggle the dialog.
The problem I have is that events are not sent if I use the dialog more than once with the same values. I’ll take an autocomplete form for example:

  • the modal dialog is opened (css class) => component is rendered with empty fields
  • I type “a” in the autocomplete => phx-change for form is triggered and results for “a” are displayed
  • I close the dialog and reopen it => component is rendered with emptied fields
  • I type the same value, “a” => nothing happens
  • Typing any other value triggers the event

What I suspect is that Liveview detects that “a” is already the latest sent value even if the assigned value was reset between the two renders of the modal dialog.

I know that the “modal” aspect is virtual in the case: the live component is rendered from the beginning and exists even if it is not visible. However, I have no clue on how to handle such situation with Liveview, and if it is possible at all. This is rather problematic when re-using live components multiple times, from what I understand at this point.

Is there a way to “force” the cached value to be cleared for a particular assign? Or maybe some other way to handle this situation?

Thanks,

You can send an event to the server whenever the modal closes (via pushEvent function in LiveView JS library) and “reset” the proper value in the assigns. You will rely on the Hooks functionality to make it work.

Here is an example:

Hooks.Example = {
  mounted() {
    const modal = document.getElementById('modalElement');
    modal.addEventListener("onClose", () => {
      this.pushEvent('clear-autocomplete', {});
    }, true);
  }
};

Of course, it needs to have the corresponding handle_event clause implemented in the Live View component.

1 Like

Can you share an example template/LV/component that demonstrates the issue. It’s hard to say what is happening without seeing the code. Thanks!

2 Likes

@jmbejar Thanks for the client side solution, with Liveview I tend to forget that “there is a client side” …

@chrismccord Thanks for taking the time investigating the issue
I created an example that can be found here: https://gist.github.com/Softknobs/435c2f0e3aac9b2ad3e7c352c6db8694

While writting it I found a workaround on server side. The behaviour mentionned in my first post happens when hidding html with html properties (including css classes):

<div id="component_id" style="<%= unless @show_component do %>display: none;<% end %>">
 ...
</div>

However values are displayed correctly if I hide the whole html code like this:

<%= if @show_component do %>
<div id="component_id">
...
</div>
<% end %>

In my case I can use the latter solution to solve the problem but there might be cases where this would not be the best solution (ie. if/else statements with duplicated html).

Using <%= if @show_component do %> instead of html properties also solves one weird problem I had in some unit tests. render_click would not render the conditionally set css class/html property in some cases. Wrapping the whole html code in a if/end instead now works. I added the failing unit test in main_live_test.exs.

As a side note, Chris, your Programming Phoenix 1.4 book is really nice. It would be nice to have a dedicated Liveview book at some point.

Thanks

1 Like