Packages
flop_phoenix
0.9.1
0.26.1
0.26.0
0.25.3
0.25.2
0.25.1
0.25.0
0.24.1
0.24.0
0.23.1
0.23.0
0.22.10
0.22.9
0.22.8
0.22.7
0.22.6
0.22.5
0.22.4
0.22.3
0.22.2
0.22.1
0.22.0
0.21.2
0.21.1
0.21.0
0.20.0
0.19.1
0.19.0
0.18.2
0.18.1
0.18.0
0.17.2
0.17.1
0.17.0
0.16.0
0.15.2
0.15.1
0.15.0
0.14.2
0.14.1
0.14.0
0.13.0
0.12.0
0.11.1
0.11.0
0.10.0
0.9.1
0.9.0
0.8.1
0.8.0
0.7.0
0.6.1
0.6.0
0.5.1
0.5.0
0.4.0
0.3.0
0.2.0
0.1.0
Phoenix components for pagination, sortable tables and filter forms using Flop.
Current section
Files
Jump to
Current section
Files
flop_phoenix
README.md
README.md
# Flop Phoenix
 [](https://hex.pm/packages/flop_phoenix) [](https://coveralls.io/github/woylie/flop_phoenix)
Flop Phoenix is an Elixir library for filtering, ordering and pagination
with Ecto, Phoenix and [Flop](https://hex.pm/packages/flop).
## Installation
Add `flop_phoenix` to your list of dependencies in the `mix.exs` of your Phoenix
application.
```elixir
def deps do
[
{:flop_phoenix, "~> 0.9.0"}
]
end
```
Follow the instructions in the
[Flop documentation](https://hex.pm/packages/flop) to set up your business
logic.
## Fetch the data
Define a function that calls `Flop.validate_and_run/3` to query the list of
pets.
```elixir
defmodule MyApp.Pets do
alias MyApp.Pet
def list_pets(params) do
Flop.validate_and_run(Pet, params, for: Pet)
end
end
```
In your controller, pass the data and the Flop meta struct to your template.
```elixir
defmodule MyAppWeb.PetController do
use MyAppWeb, :controller
alias MyApp.Pets
action_fallback MyAppWeb.FallbackController
def index(conn, params) do
with {:ok, {pets, meta}} <- Pets.list_pets(params) do
render(conn, "index.html", meta: meta, pets: pets)
end
end
end
```
You can fetch the data similarly in the `handle_params/3` function of a
`LiveView` or the `update/2` function of a `LiveComponent`.
```elixir
defmodule MyAppWeb.PetLive.Index do
use MyAppWeb, :live_view
alias MyApp.Pets
@impl Phoenix.LiveView
def handle_params(params, _, socket) do
with {:ok, {pets, meta}} <- Pets.list_pets(params) do
{:noreply, assign(socket, %{pets: pets, meta: meta})}
end
end
end
```
## HEEx templates
In your template, add a sortable table and pagination links.
```elixir
<h1>Pets</h1>
<Flop.Phoenix.table
items={@pets}
meta={@meta}
path_helper={&Routes.pet_path/3}
path_helper_args={[@socket, :index]}
headers={[{"Name", :name}, {"Age", :age}]}
row_func={fn pet, _opts -> [pet.name, pet.age] end},
opts={[for: MyApp.Pet]}
/>
<Flop.Phoenix.pagination
meta={@meta},
path_helper={&Routes.pet_path/3},
path_helper_args{[@socket, :index]},
opts={[for: MyApp.Pet]}
/>
```
`path_helper` should reference the path helper function that builds a path to
the current page. `path_helper_args` is the argument list that will be passed to
the function. If you want to add a path parameter, you can do it like this.
```elixir
<Flop.Phoenix.pagination
meta={@meta},
path_helper={&Routes.pet_path/4},
path_helper_args{[@conn, :index, @owner]},
opts={[for: MyApp.Pet]}
/>
```
If the last argument is a keyword list of query parameters, the query parameters
for pagination and sorting will be merged into that list.
The `for` option allows Flop Phoenix to determine which table columns are
sortable. It also allows it to hide the `order` and `page_size`
parameters if they match the default values defined with `Flop.Schema`.
## EEx templates
In EEX templates, you will need to call the functions directly and pass a map
with the assigns. You need to include `__changed__: nil` in the map. Do not call
the functions like this within a LiveView, since it will prevent the components
from being updated.
```elixir
<h1>Pets</h1>
<%= table(%{
__changed__: nil,
items: @pets,
meta: @meta,
path_helper: &Routes.pet_path/3,
path_helper_args: [@conn, :index],
headers: [{"Name", :name}, {"Age", :age}],
row_func: fn pet, _opts -> [pet.name, pet.age] end,
opts: [for: MyApp.Pet]
})
%>
<%= pagination(%{
__changed__: nil,
meta: @meta,
path_helper: &Routes.pet_path/3,
path_helper_args: [@conn, :index],
opts: [for: MyApp.Pet]
})
%>
```
## Clean up the template
To keep your templates clean, it is recommended to define a `table_headers/1`
and `table_row/2` function in your `View`, `LiveView` or `LiveComponent` module.
The `opts` are passed as a second argument to the `row_func`, so you can add any
additional parameters you need.
The LiveView module:
```elixir
defmodule MyAppWeb.PetLive.Index do
use MyAppWeb, :live_view
alias MyApp.Pet
alias MyApp.Pets
@impl Phoenix.LiveView
def handle_params(params, _, socket) do
with {:ok, {pets, meta}} <- Pets.list_pets(params) do
{:noreply, assign(socket, %{pets: pets, meta: meta})}
end
end
def table_headers do
[
# {display value, schema field}
{"Name", :name},
{"Age", :age},
""
]
end
def table_row(%Pet{} = pet, opts) do
socket = Keyword.fetch!(opts, :socket)
[
pet.name,
pet.age,
link "show", to: Routes.pet_path(socket, :show, pet)
]
end
end
```
The template:
```elixir
<Flop.Phoenix.table
items={@pets}
meta={@meta}
path_helper={&Routes.pet_path/3}
path_helper_args={[@socket, :index]}
headers={table_headers()}
row_func={&table_row/2},
opts={[for: MyApp.Pet, socket: @socket]}
/>
```
Refer to the `Flop.Phoenix` module documentation for more examples.