All Projects → woylie → flop

woylie / flop

Licence: MIT License
Filtering, ordering and pagination for Ecto

Programming Languages

elixir
2628 projects

Projects that are alternatives of or similar to flop

Filterable
Filtering from incoming params in Elixir/Ecto/Phoenix with easy to use DSL.
Stars: ✭ 83 (+48.21%)
Mutual labels:  pagination, filter, ecto
Jsonapi.rb
Lightweight, simple and maintained JSON:API support for your next Ruby HTTP API.
Stars: ✭ 116 (+107.14%)
Mutual labels:  pagination, filter
TableBundle
Symfony Bundle for easy pagination and filtering
Stars: ✭ 24 (-57.14%)
Mutual labels:  pagination, filter
repository
[PHP 7] Implementation and definition of a base Repository in Domain land.
Stars: ✭ 26 (-53.57%)
Mutual labels:  pagination, filter
Datagrid
Datagrid for Laravel v5
Stars: ✭ 44 (-21.43%)
Mutual labels:  pagination, filter
Queryql
Easily add filtering, sorting, and pagination to your Node.js REST API through your old friend: the query string!
Stars: ✭ 76 (+35.71%)
Mutual labels:  pagination, filter
Tablefilter
A Javascript library making HTML tables filterable and a bit more :)
Stars: ✭ 248 (+342.86%)
Mutual labels:  pagination, filter
react-strap-table
react table (client and server-side) based on bootstrap.
Stars: ✭ 28 (-50%)
Mutual labels:  pagination, filter
ember-cli-blog
Tom Dale's blog example updated for the Ember CLI
Stars: ✭ 87 (+55.36%)
Mutual labels:  pagination, filter
Gridify
Easy and optimized way to apply Filtering, Sorting, and Pagination using text-based data.
Stars: ✭ 372 (+564.29%)
Mutual labels:  pagination, ordering
spring-boot-jpa-rest-demo-filter-paging-sorting
Spring Boot Data JPA with Filter, Pagination and Sorting
Stars: ✭ 70 (+25%)
Mutual labels:  pagination, filter
Sieve
⚗️ Clean & extensible Sorting, Filtering, and Pagination for ASP.NET Core
Stars: ✭ 560 (+900%)
Mutual labels:  pagination, filter
Gridjs
Advanced table plugin
Stars: ✭ 3,231 (+5669.64%)
Mutual labels:  pagination, filter
ex sieve
Implement dynamic filtering and sorting API for Ecto queries
Stars: ✭ 37 (-33.93%)
Mutual labels:  filter, ecto
Graphql To Mongodb
Allows for generic run-time generation of filter types for existing graphql types and parsing client requests to mongodb find queries
Stars: ✭ 261 (+366.07%)
Mutual labels:  pagination, filter
Rummage ecto
Search, Sort and Pagination for ecto queries
Stars: ✭ 190 (+239.29%)
Mutual labels:  pagination, ecto
Filtrex
A library for performing and validating complex filters from a client (e.g. smart filters)
Stars: ✭ 157 (+180.36%)
Mutual labels:  filter, ecto
phoenix pagination
Simple pagination for Ecto and Phoenix that uses plain EEx templates.
Stars: ✭ 20 (-64.29%)
Mutual labels:  pagination, ecto
express-mquery
Expose mongoose query API through HTTP request.
Stars: ✭ 37 (-33.93%)
Mutual labels:  pagination, filter
Exopite-Multifilter-Multi-Sorter-WordPress-Plugin
Display and/or sort/filter any page or post types by multiple taxonomies or terms (like post by categories and/or tags) with AJAX. Exopite multifilter, multi-sortable, multi selectable, multi filterable sortable Wordpress Plugin.
Stars: ✭ 18 (-67.86%)
Mutual labels:  pagination, filter

Flop

CI Hex Coverage Status

Flop is an Elixir library that applies filtering, ordering and pagination parameters to your Ecto queries.

Features

  • offset-based pagination with offset/limit or page/page_size
  • cursor-based pagination (aka key set pagination), compatible with Relay pagination arguments
  • ordering by multiple fields in multiple directions
  • filtering by multiple conditions with various operators on multiple fields
  • parameter validation
  • configurable filterable and sortable fields
  • join fields
  • compound fields
  • query and meta data helpers
  • Relay connection formatter (edges, nodes and page info)
  • UI helpers and URL builders through Flop Phoenix.

Status

This library has been used in production for a while now. Nevertheless, there may still be API changes on the way to a more complete feature set.

Installation

Add flop to your list of dependencies in mix.exs:

def deps do
  [
    {:flop, "~> 0.16.0"}
  ]
end

If you want to configure a default repo, add this to your config file:

config :flop, repo: MyApp.Repo

Alternatively, you can add a configuration module. For more information, refer to the Flop module documentation.

Usage

Define sortable and filterable fields

To configure the sortable and filterable fields, derive Flop.Schema in your Ecto schema. While this step is optional, it is highly recommend, since the parameters you will pass to the Flop functions will come from the user side and should be validated. Deriving Flop.Schema will ensure that Flop only applies filtering and sorting parameters on the configured fields.

defmodule MyApp.Pet do
  use Ecto.Schema

  @derive {
    Flop.Schema,
    filterable: [:name, :species],
    sortable: [:name, :age, :species]
  }

  schema "pets" do
    field :name, :string
    field :age, :integer
    field :species, :string
    field :social_security_number, :string
  end
end

You can also define join fields, compound fields, max and default limit, and more. See the Flop.Schema documentation for all the options.

Query data

You can use Flop.validate_and_run/3 or Flop.validate_and_run!/3 to validate the Flop parameters, retrieve the data from the database and get the meta data for pagination in one go.

defmodule MyApp.Pets do
  import Ecto.Query, warn: false

  alias Ecto.Changeset
  alias Flop
  alias MyApp.{Pet, Repo}

  @spec list_pets(Flop.t()) ::
          {:ok, {[Pet.t()], Flop.Meta.t}} | {:error, Changeset.t()}
  def list_pets(flop \\ %Flop{}) do
    Flop.validate_and_run(Pet, flop, for: Pet)
  end
end

The for option sets the Ecto schema for which you derived Flop.Schema. If you didn't derive Flop.Schema as described above and don't care to do so, you can omit this option (not recommended, unless you only deal with internally generated, safe parameters).

On success, Flop.validate_and_run/3 returns an :ok tuple, with the second element being a tuple with the data and the meta data.

{:ok, {[%Pet{}], %Flop.Meta{}}}

Consult the docs for more info on the Meta struct.

If you prefer to validate the parameters in your controllers, you can use Flop.validate/2 or Flop.validate!/2 and Flop.run/3 instead.

defmodule MyAppWeb.PetController do
  use MyAppWeb, :controller

  alias Flop
  alias MyApp.Pets
  alias MyApp.Pets.Pet

  action_fallback MyAppWeb.FallbackController

  def index(conn, params) do
    with {:ok, flop} <- Flop.validate(params, for: Pet) do
      pets = Pets.list_pets(flop)
      render(conn, "index.html", pets: pets)
    end
  end
end

defmodule MyApp.Pets do
  import Ecto.Query, warn: false

  alias Flop
  alias MyApp.Pets.Pet
  alias MyApp.Repo

  @spec list_pets(Flop.t()) :: {[Pet.t()], Flop.Meta.t}
  def list_pets(flop \\ %Flop{}) do
    Flop.run(Pet, flop, for: Pet)
  end
end

If you only need the data, or if you only need the meta data, you can also call Flop.all/3, Flop.meta/3 or Flop.count/3 directly.

If you didn't configure a default repo as described above or if you want to override the default repo, you can pass it as an option to any function that uses the repo:

Flop.validate_and_run(Pet, flop, repo: MyApp.Repo)
Flop.all(Pet, flop, repo: MyApp.Repo)
Flop.meta(Pet, flop, repo: MyApp.Repo)
# etc.

See the docs for more detailed information.

Internal parameters

Flop is built to handle parameters generated by a user. While you could manipulate those parameters and add additional filters when you receive them, it is recommended to cleanly separate the parameters you get from the outside and the parameters that your application needs to add internally.

For example, if you need to scope a query depending on the current user, it is preferred to add a separate function that adds the necessary WHERE clauses:

def list_pets(%{} = args, %User{} = current_user) do
  Pet
  |> scope(current_user)
  |> Flop.validate_and_run(flop, for: Pet)
end

defp scope(q, %User{role: :admin}), do: q
defp scope(q, %User{id: user_id}), do: where(q, user_id: ^user_id)

To add additional filters that can only be used internally without exposing them to the user, you can pass them as a separate argument. You can use the same argument to override certain options depending on where the function is used.

def list_pets(%{} = args, opts \\ [], %User{} = current_user) do
  flop_opts =
    opts
    |> Keyword.take([
      :default_limit,
      :default_pagination_type,
      :pagination_types
    ])
    |> Keyword.put(:for, Pet)

  Pet
  |> scope(current_user)
  |> apply_filters(opts)
  |> Flop.validate_and_run(flop, flop_opts)
end

defp scope(q, %User{role: :admin}), do: q
defp scope(q, %User{id: user_id}), do: where(q, user_id: ^user_id)

defp apply_filters(q, opts) do
  Enum.reduce(opts, q, fn
    {:last_health_check, dt}, q -> where(q, [p], p.last_health_check < ^dt)
    {:reminder_service, bool}, q -> where(q, [p], p.reminder_service == ^bool)
    _, q -> q
  end)
end

Flop Phoenix

Flop Phoenix is a companion library that defines view helpers for use in Phoenix templates.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].