bogdan / datagrid

Gem to create tables grids with sortable columns and filters
MIT License
1.02k stars 115 forks source link

Ability to define partials for additional filter types #321

Closed jkaufman closed 7 months ago

jkaufman commented 7 months ago

It appears that only the range filter allows setting a custom partial (via a partials option passed to datagrid_form_for). I was hoping to define a _column_names_filter partial. However, customization of enum filter rendering is limited to _enum_checkboxes.

bogdan commented 7 months ago

It is hard to imagine what kind of filters need a separated partial. Long ago there was only one partial for all of them. I don't see how to do it adequately: some people may want integer range and date range to have different layout or between integer and float.

I believe the best thing to do is to add a condition inside _enum_checkboxes.

jkaufman commented 7 months ago

That's understandable. My specific goal was to to lay out the column options in a dropdown menu. I was able to accomplish this by creating a view component that wraps filter and rendering it in _form.html.erb.

bogdan commented 7 months ago

You may share the HTML layout you want to generate and can think of how we can make it easier to achive.

jkaufman commented 7 months ago

This is how I'm customizing the :column_names filter.

_form.html.erb:

<%= form_for grid, options.merge({html: {class: "my-4 flex items-center"}}) do |f| -%>
  <% grid.filters.each do |filter| %>
    <% if filter.name == :column_names %>
      <%= render(MyGrid::ColumnNamesFilterComponent.new(form:f, filter:filter)) %>
    <% else %>
      <div class="datagrid-filter filter flex items-center mr-3">
          <%= f.datagrid_label filter %>
          <%= f.datagrid_filter filter %>
      </div>
    <% end %>
  <% end %>

column_names_filter_component.html.erb:

<div class="relative">
  <input type="checkbox" id="colsbox" class="absolute sr-only peer"/>
  <%= content_tag :label, for: "colsbox", id: "colsbox-label", class: "flex items-center space-x-1 cursor-pointer peer-checked:opacity-50 group" do %>
    <%= content_tag(:span, @filter.header) %>
    <svg id="colsbox-chevron" class="h-4 w-4 peer-checked:group-[]:hidden" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
    </svg>
    <svg id="colsbox-x" class="h-4 w-4 hidden peer-checked:group-[]:block" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" >
        <path d="M8 8 L20 20 M8 20 L20 8" stroke-width="2"/>
    </svg>
  <% end %>
  <div id="colsboxmenu" class="flex flex-col absolute mt-1 left-1 top-full min-w-max shadow rounded opacity-0 bg-white p-2 border border-gray-400 transition delay-75 ease-in-out z-10 peer-checked:opacity-100">
      <%= @form.datagrid_filter @filter, class: "option flex items-center"%>
  </div>
</div>
bogdan commented 7 months ago

I don't see any better name of achieving that than you did. I personally prefer custom forms instead of just looping over grid.filters. There is no other way if you need fancy interface. Admin panel can live with generated one, but only to some extend as frequently used reports may require UI improvements.

jkaufman commented 7 months ago

Totally. I didn’t realize that was an option when I began. Is there documentation or a reference implementation of a completely custom UI that doesn’t simply override _form?

bogdan commented 7 months ago

Look here: https://github.com/bogdan/datagrid/wiki/Frontend#advanced-method

Probably it may need more examples.

jkaufman commented 7 months ago

Reading it again, it makes sense to me. Thank you!