Paginate when I have two tables in the same page

Hey!

I have a liveview page that holds two flop tables. Everything works well with filters, as I’m using on_change for my filter_form and that works great. I’m able to keep an assign for each of my table filters.

The problem is that I don’t have this kind of mechanism for pagination, where I can push events (instead of changing the querystring params). Query strings would be nice to have, but is there a way for me to paginate both tables independently? Maybe I’m missing something?

Hello and welcome to the forum!

Are you storing just the filters as opposed to the whole %Flop.Meta{} structs? This struct contains all flop info including filters, pagination, and sorting. You could also take a look at the following two functions from Flop Phoenix for how to manipulate and combine them into query params:

I’ve never done multiple tables on page so you might also need to use the URI module from Elixir’s standard library.

1 Like

You can use on_paginate and on_sort to push an event instead of changing the URL.

<Flop.Phoenix.table
  items={@items}
  meta={@meta}
  on_sort={JS.push("sort-pets")}
/>

<Flop.Phoenix.pagination
  meta={@meta}
  on_paginate={JS.push("paginate-pets")}
/>

https://hexdocs.pm/flop_phoenix/Flop.Phoenix.html#module-using-js-commands

Does that help?

1 Like

Greetings. Love your library.

What’s the right place to hook a control to set the page size in LiveView? I have a filter form and am deriving default Flop.Schema.

-bt

I think you have two options here.

Option 1: Add a separate form for that control and add an event handler similar to:

def handle_event("set-page-size", %{"page_size" => page_size}, socket) do
    flop = %{socket.assigns.meta.flop | page_size: page_size}
    path = Flop.Phoenix.build_path(~p"/entities", flop)
    {:noreply, push_patch(socket, to: path)}
  end

Or if you don’t care about having the filter parameters in the URL, query the data right there.

Option 2: The filter_fields component renders a hidden input for the page size. You should be able to place a page size input after filter_fields. If we adapt the example from the readme, it might look something like this:

  ~H"""
  <.form
    for={@form}
    id={@id}
    phx-target={@target}
    phx-change={@on_change}
    phx-submit={@on_change}
  >
    <.filter_fields :let={i} form={@form} fields={@fields}>
      <.input
        field={i.field}
        label={i.label}
        type={i.type}
        phx-debounce={120}
        {i.rest}
      />
    </.filter_fields>
    
    <input type="text" name="page_size" value={@meta.page_size} />

    <button class="button" name="reset">reset</button>
  </.form>
  """
1 Like

That worked flawlessly. I took the first option, but the second would work for some designs. Would you like a PR for documentation of this feature, or no? Particularly, the build_path and the right place to hook custom filter fields were hard to find.

2 Likes

After working with this library for a bit, I wholeheartedly recommend it. I love that everything is done through navigation links, so the whole browser experience on the liveview page is wonderful. There are lots of options to hook everything we need. Thanks for your time on this.

4 Likes

A PR would be appreciated!