"push_patch" won't update URL

I have a component for pagination. It works but there’s one issue: it won’t replace or update the URL in the browser dynamically. Namely, when I change a page – 2nd, 3rd, 4th page of the data in a table – I want the URL to get updated as well: updated in the browser URL bar and appended to the browser history.

my_domain.com/my/pigs?page=2&page_size=5
my_domain.com/my/pigs?page=3&page_size=5
my_domain.com/my/pigs?page=66&page_size=5

But at the moment only data will get fetched correctly, according to the current page, whereas the URL will remain static always - my_domain.com/my/pigs:

  @impl true
  def handle_info({:update, opts}, socket) do
    extra_params = merge_and_sanitize_params(socket, opts)
    path = "/my/pigs"
    to = path <> "?" <> URI.encode_query(extra_params)

    # socket = push_patch(socket, to: to, replace: true)
    socket = push_patch(socket, to: to)

    {:noreply, socket}
  end

I’ve tried replace with true, and without – the URL will stay “my/pigs” no matter what.

The _url in handle_params(..) will contain the correct one – with ?page=X&page_size=Y which is correct:

  @impl true
  def handle_params(params, _url, socket) do
    # _url will contain dynamic url, with the correct params
    # .....

However, the the URL in browser the will still remain static.

What’s the matter?

How about

socket = push_patch(socket, to: ~p"/my/pigs?#{extra_params}")

Why? to already will contain that – URL with the correct query string.

I don’t think handle_info is the best callback to handle this job.

Live navigation is setup specifically for the use case you are describing.

Here’s a section of the documentation using pagination as an example:

For example, imagine you have a blog. The URL for a single post is: “/blog/posts/:post_id”. In the post page, you have comments and they are paginated. You use <.link patch={...}> to update the shown comments every time the user paginates, updating the URL to “/blog/posts/:post_id?page=X”. In this example, you will access "post_id" on mount/3 and the page of comments on handle_params/3.

It may not be the best one. I need to find the source of the issue rather than the best callback, though.

Here’s a part of my pagination component

      <div class="page-stepper">
        <%= for {page_number, current_page?} <- pages(@pagination) do %>
          <div phx-click="show_page"
            phx-value-page={page_number}
            phx-target={@myself}
            class={if current_page?, do: "active"}
          ><%= page_number %></div>
        <% end %>
      </div>

And

# ...........
  def handle_event("show_page", params, socket) do
    # ..........
    # opts ---> page, page_size
    # 
    send(self(), {:update, opts})
    {:noreply, socket}
    # ........
1 Like