LiveView updated hook problem


We are developing our project fully in LiveView and are very excited about possibilities it provides. There are a couple of places in our code where we need to use JavaScript hooks (e.g. for autocomplete fields). However, while using those we encountered some behaviour of the updated hook we didn’t expect.

We want to be able to bind a hook to a dom element and expect it to be triggered only if a assigns value for that element changes (@selected_tab here). Here is the code:

<div phx-hook="initTabHooksGeocoder" data-selected-tabs="<%=@selected_tab %>" id="geocode-isolated"></div>
<div id="content">
    <div class="date-initiator-checker autocomplete-initiator-checker" id="observe" phx-hook="datepickerShipmentCard">
      <%= case @selected_tab do
        "Segments" -> render(VoF.BOWeb.PartialsView, "segment_tab.html", assigns) 
        "Commission" -> render(VoF.BOWeb.PartialsView, "commission_tab.html") 
        end %>

As you can see, an element with a initTabHooksGeocoder hook is isolated and has no children, whereas the element with an id content renders segment_tab.html template.
In the segment_tab.html template there is the code the opens up a modal on click:

<button phx-click="open-modal">Split</button>
<div class="modal <%= if @open_modal do %> active<% end %>">
    <%= render("split-segment-modal.html", assigns) %>

So if a @open_modal variable is truthy, the modal will be opened. Here is the handle_event callback from our live component that will set that value:

def handle_event("open-modal", _, socket) do
  {:noreply, assign(socket, :open_modal, true)}

Since the isolated div (the one with the initTabHooksGeocoder hook) is in no way related (not a parent) to the html code that opens the modal, we expect that the updated hook won’t be triggered when the modal is being opened. However, against our expectations, the following code will be executed and we will see the console.log in the console:

LiveHooks.initTabHooksGeocoder = {
    console.log('UPDATED dataset',this.el.dataset);
    AutocompleteModule._init('.autocomplete', liveSocket, LiveHooks,'#form','.form-input-triggering-change', autoCompleteCheckers);

Any help is highly appreciated!


Are you able to isolate the problem with a minimal example - e.g. is it related to nested rendering of templates, or do the hooks fire when any assign changes when you have a single large template?

We’ve tried on some other, less, demanding, pages without nesting. The hooks fire when socket.assigns is changed. We’ve tested this, by changing handle_event so that the socket stays intact.
def handle_event(“open-modal”, _, socket) do
{:noreply, socket}
In this case no hooks were fired.

1 Like

Hi @ljuba - I was able to reproduce so went looking through open bug reports on the liveview github project - it looks like we found the same one -

Are you able to code around it? In my case it doesn’t matter if the Hook update fires multiple times.

Hey @mindok, unfortunately we are currently not able to code around this problem which is truly a showstopper for us… While we are looking for a workaround, we are hoping to hear from @chrismccord or @josevalim

We will be able to go around it, but it would be helpful to know if this is desired behavior or a bug, because it is not a small effort to rewrite what we’ve made so far in past couple of months. We are preparing production with LiveView and we have very intensive js/components frontend(Custom autocompletes, datepickers, accordions, maps, modals …), and this kind of behavior means that we can’t initialize js components in updated() callback because it will re-render all components on every update of a socket assigns. Thanks for reply though. It means allot when you know that you are not alone with this peace of tech :smiley:

If it’s going to be a costly issue for you, it may be worth taking a look at the liveview js and see if you can resolve it, and submit a PR… the hook firing is relatively easy to find (search for triggerHooks in, but from a very brief look at the code I would guess the list of changes isn’t quite right, and I suspect that’s more complex to resolve…

Have you also turned liveview debugging on to make sure the right diffs are getting delivered from the server to the browser, so you can isolate between server side liveview issues and client-side.

I’ve already spent some time on that js file. It looks to me that the problem is in elixir. In the part for finding diffs. Logger is turned on from the day one, but we’ve took some things for granted. My team and I had mutual agreement on understanding hooks. Now, it is not the bug that is problem but paradigm that we adopted and based our front end architecture around it. Basically we now just need to know if this is desired behavior or not. Then we can re-plan our project. Thanks for reply, if we don’t receive any answer I will, for sure, try to resolve this issue(if it is an issue) :smiley:

I’m facing today the same issue with some of my liveview code. I had the same understanding as you regarding the fact that phx_hook should only be triggered for elements that have actually been updated via assigns.
So I’m highly interested by any progress you have made regarding this issue.

1 Like

We did not received any information regarding the question “is this desired behavior?”, but we’ve found similar git issue that has been declared as bug.
I was not trying to fork the project and resolve the issue, because we did not know if this kind of behavior is an actual issue.
We’ve made backup plan that involves changes regarding our UX.
If you have SPA like front architecture, the only way is to use ‘old school’, almost ‘ajaxish’, approach where you use only pushWithReply to fill assigns without updating components in form. That means that you must have a submit button and custom handling of submitting forms because form needs to be ignored. It is ugly and completely eliminates the purpose of liveView as a new piece of tech.
So to keep the story short, the only way to go around it is not to use it, and fallback on pure phoenix. We do hope that this is an issue and that will be resolved soon. Thank you for you question and if we find something new, we will post it here.

I’ve upgraded today to liveview 0.5.2 (was using 0.4.1 before) and the problem described by the original poster seems to be solved for me.
At least my usecase is fixed now.


Thanks for feedback.
Unfortunately problem still remains on our side :frowning: