View Source Backpex.Filter behaviour (Backpex v0.3.0)
The base behaviour for all filters. Injects also basic layout, form and delete button for a filters rendering.
Enabling filters on a resources index view is a two step process:
- Add modules implementing one of the behaviors from the
Backpex.Filtersnamespace to your project.
- We suggest to use a
MyAppWeb.Filters.<FILTERNAME>convention. - We implemented the
__using__macro for the filters, injecting code like imports (e.g.Ecto.Query) and functions (e.g.render/1) into your module.
- Implement the
filters/0callback on your resource.
The latter just returns a keyword list with the field names as keys and the filter module as values.
# in your resource configuration file
@impl Backpex.LiveResource
def filters, do: [
status: %{
module: MyAppWeb.Filters.EventStatusSelect
},
begins_at: %{
module: MyAppWeb.Filters.DateRange
},
published: %{
module: MyAppWeb.Filters.EventPublished
}
]Custom filters
Instead of using the pre-defined filters you can also define custom filters by using Backpex.Filter and implementing at least query/3, render/1 and render_form/1.
For example purposes let's define a custom select filter:
defmodule MyApp.Filters.CustomSelectFilter do
use BackpexWeb, :filter
@impl Backpex.Filter
def label, do: "Event status"
@impl Backpex.Filter
def render(assigns) do
assigns = assign(assigns, :label, option_value_to_label(options(), assigns.value))
~H"""
<%= @label %>
"""
end
@impl Backpex.Filter
def render_form(assigns) do
~H"""
<.form_field
type="select"
selected={selected(@value)}
options={my_options()}
form={@form}
field={@field}
label=""
/>
"""
end
@impl Backpex.Filter
def query(query, attribute, value) do
where(query, [x], field(x, ^attribute) == ^value)
end
defp option_value_to_label(options, value) do
Enum.find_value(options, fn {option_label, option_value} ->
if option_value == value, do: option_label
end)
end
defp my_options, do: [
{"Select an option...", nil},
{"Open", :open},
{"Close", :close},
]
defp selected(""), do: nil
defp selected(value), do: value
endFilter presets
To define presets for your filters, you need to add a list of maps under the key of :presets to your filter in your LiveResource.
Each of those maps has two keys:
:label– simply the String shown to the user:values– a function with arity 0 that returns the values corresponding to your used filter
See the example below for
:valuesreturn values for the default range and boolean filter
@impl Backpex.LiveResource
def filters, do: [
begins_at: %{
module: MyAppWeb.Filters.DateRange,
label: "Begins At",
presets: [
%{
label: "Last 7 Days",
values: fn -> %{
"start" => Date.add(Date.utc_today(), -7),
"end" => Date.utc_today()
}
end
}
},
published: %{
module: MyAppWeb.Filters.EventPublished,
presets: [
%{
label: "Both",
values: fn -> [:published, :not_published] end
},
%{
label: "Only published",
values: fn -> [:published] end
}
]
}
]
Summary
Callbacks
Defines whether the filter can be used or not.
If no label is defined on the filter map, this value is used as the filter label.
The filter query that is executed if an option was selected.
Renders the filters selected value(s).
Renders the filters options form.
Callbacks
@callback can?(Phoenix.LiveView.Socket.assigns()) :: boolean()
Defines whether the filter can be used or not.
@callback label() :: String.t()
If no label is defined on the filter map, this value is used as the filter label.
@callback query(Ecto.Query.t(), any(), any()) :: Ecto.Query.t()
The filter query that is executed if an option was selected.
@callback render(Phoenix.LiveView.Socket.assigns()) :: Phoenix.LiveView.Rendered.t()
Renders the filters selected value(s).
@callback render_form(Phoenix.LiveView.Socket.assigns()) :: Phoenix.LiveView.Rendered.t()
Renders the filters options form.