Flop adapter

Copy Markdown

Refine.Flop is an adapter for using Flop with Refine.

The adapter translates Flop's filter and pagination parameters into Refine search options. Facets remain part of Refine's own options, while Flop handles field filters and offset pagination.

Installation

Add Flop to your deps (check for the most recent version):

{:flop, "~> 0.26"}

Usage

If you are starting with Flop, follow the setup instructions to add a Flop schema to your Ecto schema.

For an application that already uses Flop, no changes are needed.

Searches are called with Refine.Flop.search/3 - this is basically the Refine.search/2 function with Flop parameters added. The return value is equal to Refine.search, with the addition of key flop_meta with a Flop.Meta struct.

Filtering

flop_params = %{filters: [%{field: :title, op: :ilike, value: "ghost"}]}
Refine.Flop.search(config, flop_params, repo: Repo, for: Article)

In this example:

  • for is a Flop option that builds a query for that schema.
  • repo can be omitted when the repo is configured globally.

Flop parameters can also be passed as a string-keyed map, for example from URL parameters:

flop_params = %{"filters" => [%{"field" => "title", "op" => :ilike, "value" =>  "ghost"}]}
Refine.Flop.search(config, flop_params, repo: Repo, for: Article)

Filtering with a base query

A base query can be used together with Flop filters.

query = from a in Article, where: a.draft == false
flop_params = %{filters: [%{field: :title, op: :ilike, value: "ghost"}]}
Refine.Flop.search(config, flop_params, query: query, repo: Repo)

In this example:

  • where clauses from both sources will be combined.
  • for can be omitted when using query.

Filtering with facets

Pass facet options in the same way as with Refine.search.

flop_params = %{filters: [%{field: :title, op: :ilike, value: "ghost"}]}
facets = %{"tag" => ["stories"]}

Refine.Flop.search(config, flop_params,
  facets: facets,
  repo: Repo,
  for: Article
)

Sorting

Flop's order_by and order_directions are applied to the results, including Flop's null-ordering directions (for example :asc_nulls_last). Sortable fields must be columns of the source table or fields included in the base query's select.

flop_params = %{
  order_by: [:draft, :title],
  order_directions: [:desc, :asc]
}

Refine.Flop.search(config, flop_params,
  repo: Repo,
  for: Article
)

To override Flop's ordering, pass Refine's own order_by option - it replaces Flop's ordering entirely. See order_by for its format.

If order_by is both passed in Flop parameters and in Refine search options, the latter will override Flop's parameters.

Generating Refine search options from Flop

Instead of passing Flop parameters directly to Refine.Flop.search/3, use Refine.Flop.to_search_options/2 to inspect or modify the generated Refine search options before passing them to Refine.search/2.

This does not return the Flop.Meta struct.

search_options = Refine.Flop.to_search_options(flop_params, repo: Repo, for: Article)
# Optionally modify search options
Refine.search(config, search_options)

Notes

  • Offset-based pagination is supported, in both of Flop's forms: page/page_size and limit/offset. Both are translated to Refine's limit and offset.
  • Cursor-based pagination is not supported.
  • Flop filters on joined fields require the joins to be present in the base query, the same as any Refine base query.
  • If used, Flop option for must correspond to Refine's configured source table.