woylie / flop_phoenix

Components for pagination, sortable tables and filter forms using Phoenix, Ecto and Flop
MIT License
392 stars 44 forks source link

Helper for independent table column sorter #22

Closed jesse-iluminai closed 3 years ago

jesse-iluminai commented 3 years ago

Mathias I saw that with the new sort table that you put in the last couple of days you have included some basic column sorting capabilities (I haven't used it, not working with LiveView just yet).

How difficult do you think it would be for you to extract the work you've done to produce a modifiable sort_column helper to use where we'd like on our own custom table layouts.

It might take at least the signature: sort_column(flop, column_name, display_name, *) where column_name is one of the whitelisted values from Flop, and display_name is whatever we'd like. I could use build in icons or any other function we'd like to hold the direction (something like you already have for customizing pagination links would be awesome).

I've been playing around basically looking at:

<table>
  <thead>
    <th><%= sort_column(@meta, :name, gettext("Name"), *)</th>
    <th><%= sort_column(@meta, :active, gettext("Status"), *)</th>
  </thead>
  <tbody>

  </tbody>
</table>

What do you think? Is the work extractable into a more tailored approach separate from the basic sorttable?

woylie commented 3 years ago

You can use the sortable table I built in regular .eex templates as well, you don't necessarily need LiveView.

You can generate a link for sorting like this:

Flop.Phoenix.build_path(
  &Routes.some_path_helper/2,
  [@conn, :index],
  Flop.push_order(@meta.flop, :name)
)

You could put that in a view function and call it in your template:

<th><%= link gettext("Name"), to: sort_path(@conn, @meta, :name) %></th>

But if all you want is to customise what is displayed in the header, this is already possible with the table/1 function. The headers parameter is a list of tuples, where the first parameter is the display value. So instead of passing a string, you can also pass additional markup like this:

def table_headers do
  [
    {
      content_tag :div, class: "some-class" do
       "Name"
      end,
      :name
    }
  ]
end

table(%{
      headers: table_headers(),
      # ...
  })

And for customising the asc/desc indicator symbol displayed next to the header column value, you can use the symbol_class, symbol_asc and symbol_desc options. symbol_asc and symbol_desc can be simple strings like the default values, or any markup you can generate with Phoenix.HTML.

Is there some customisation you need that you cannot accomplish with these options?

jesse-iluminai commented 3 years ago

Thanks for the hints Mathias - I'll give that a try. Mainly I prefer to separate my concerns of display (HTML/table) and code (sort helpers) but I think with what you've provided me here already will help a lot.

When raising these items lately mainly I've been going back to my laundry list of nice to haves in order to provide the community with a legit pagination/sort/filtering solution which people can lean on. Would love to see this as a go-to solution in our meager package space. This is great for me to be able to work through your toolset you've provided (and all the effort you've put into it) to battle test it a little and I understand you have your day job. Appreciate you also being so responsive here.

jesse-iluminai commented 3 years ago

With your suggestions I managed to use the build_path/3 function and create a helper for myself to use along the lines of <%= sort_column(@meta, :name, gettext("Name"), *) %> within my templates.

Next up, as my queries are starting to be more interesting, need to explore with you support for joins :). I've created a ticket over in Flop to help track and see what you think.

You can close this off at any point.

woylie commented 3 years ago

Glad you could make it work. I might move some of the private functions for retrieving the order for a given field to Flop in the future.