How to implement conditional phx-update (append or replace) with Phoenix LiveView?

Hi guys. First of all, LiveView is awesome. Thanks to everyone contributing.

I have a page with a filter (search and sort) and “load more” type pagination.

I’m using temporary_assigns for the collection of items and phx-update="append" for the pagination.

However, when filter form is changed, I want the collection items to be replaced instead of appended. When, for example, the sorting is changed, the collection of items should start from page 1.

So is it possible to alter the behaviour of phx-update conditionally? How can I utilize the functionalities of both append and replace in the same view/component?

I have tried hooking the form to empty the collection, but failed:

Hooks.Replace = {
    beforeUpdate() {
        const nodeEmptied = document.getElementById("to-be-replaced-elem");
        while (nodeEmptied.firstChild) {
            nodeEmptied.removeChild(nodeEmptied.firstChild);
        }
    }
}

Any help would be greatly appreciated.

You don’t need hooks for this. Here’s my approach:

phx-update can take 4 possible values:

    replace - the default operation. Replaces the element with the contents
    ignore - ignores updates to the DOM regardless of new content changes
    append - append the new DOM contents instead of replacing
    prepend - prepend the new DOM contents instead of replacing

I created a new assign :update_action and I’m passing it like this to the template: phx-update="<%= @update_action %>"

So, you only need to switch between append or replace in the :update_action assign depending on your logic.

However, when filter form is changed, I want the collection items to be replaced instead of appended. When, for example, the sorting is changed, the collection of items should start from page 1.

Here, you would change :update_action to replace.

When you only load more without actually changing any filters, it would be in append state.

So, in initial mount, it’s set to append
Then, in handle_params it’s set to replace since this is where the logic happens when filtering
Then, in handle_event("load-more", _, _), I set it again to append

Hope this helps.

13 Likes

It works. Thanks for sharing your solution!

3 Likes

Thanks, this is super helpful. I haven’t seen this solution mentioned elsewhere.

Perhaps it should be in the LiveView docs?