From backpex
Creates filter modules for Backpex LiveResources with types: Boolean, Select, MultiSelect, Range, and Custom. Use when adding filters to Backpex index views.
How this skill is triggered — by the user, by Claude, or both
Slash command
/backpex:create-filterThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
When the user wants to add a filter:
When the user wants to add a filter:
filters/0 callback| Type | Use for | use module | Key callbacks |
|---|---|---|---|
| Boolean | Checkbox predicates (published yes/no) | Backpex.Filters.Boolean | options/1 returning %{label, key, predicate} maps |
| Select | Single-value dropdown | Backpex.Filters.Select | prompt/0, options/1 returning {label, value} tuples |
| MultiSelect | Multi-value dropdown with checkboxes | Backpex.Filters.MultiSelect | prompt/0, options/1 returning {label, value} tuples |
| Range | Date, datetime, or number ranges | Backpex.Filters.Range | type/0 returning :date, :datetime, or :number |
| Custom | Anything else | Backpex.Filter | query/4, render/1, render_form/1 |
All built-in filters auto-implement query/4, render/1, and render_form/1. Do NOT re-implement those unless you need custom behavior.
All filters have these overridable callbacks with defaults:
label/0: filter label (optional callback, can also be set in filters/0 map)can?/1: visibility control, receives assigns, default truetype/1: Ecto type for validation (default :string), receives assignschangeset/3: custom changeset validation (default: no-op)validate/2: public validation API, builds changeset from type/1 and changeset/3Multiple options selectable via checkboxes, combined with OR. Predicates use Ecto.Query.dynamic/2.
defmodule MyAppWeb.Filters.PostPublished do
use Backpex.Filters.Boolean
import Ecto.Query
@impl Backpex.Filter
def label, do: "Published?"
@impl Backpex.Filters.Boolean
def options(_assigns) do
[
%{label: "Published", key: "published", predicate: dynamic([x], x.published)},
%{label: "Not published", key: "not_published", predicate: dynamic([x], not x.published)}
]
end
end
Single-value dropdown. Default query/4 does WHERE field = value.
defmodule MyAppWeb.Filters.PostCategorySelect do
use Backpex.Filters.Select
import Ecto.Query
alias MyApp.Repo
@impl Backpex.Filter
def label, do: "Category"
@impl Backpex.Filters.Select
def prompt, do: "Select category ..."
@impl Backpex.Filters.Select
def options(_assigns) do
from(c in MyApp.Category, select: {c.name, c.id}, order_by: c.name) |> Repo.all()
end
end
Same as Select but allows multiple values. Default query/4 does WHERE field IN values. Uses prompt/0 (implement with @impl Backpex.Filters.Select) and options/1 (implement with @impl Backpex.Filters.MultiSelect). Note: MultiSelect internally sets @behaviour Backpex.Filters.Select for the prompt callback.
Renders "From" and "To" inputs. Note: type/0 is arity 0, not arity 1.
defmodule MyAppWeb.Filters.PostLikeRange do
use Backpex.Filters.Range
@impl Backpex.Filters.Range
def type, do: :number
@impl Backpex.Filter
def label, do: "Likes"
end
For dates use def type, do: :date. For datetimes use def type, do: :datetime.
Use Backpex.Filter directly when no built-in type fits. You must implement query/4, render/1, and render_form/1. Note: use Backpex.Filter does not import HEEx sigils. You need use Phoenix.Component for ~H support.
defmodule MyAppWeb.Filters.PostCustom do
use Phoenix.Component
use Backpex.Filter
import Ecto.Query
@impl Backpex.Filter
def label, do: "Custom"
@impl Backpex.Filter
def query(query, attribute, value, _assigns) do
where(query, [x], field(x, ^attribute) == ^value)
end
@impl Backpex.Filter
def render(assigns) do
~H"{@value}"
end
@impl Backpex.Filter
def render_form(assigns) do
~H"""
<input type="text" name={@form[@field].name} value={@value} class="input input-sm" />
"""
end
end
filters/0 returns a keyword list. Each key is the schema field atom being filtered.
@impl Backpex.LiveResource
def filters do
[
published: %{
module: MyAppWeb.Filters.PostPublished
},
category_id: %{
module: MyAppWeb.Filters.PostCategorySelect,
label: "Category"
},
likes: %{
module: MyAppWeb.Filters.PostLikeRange,
label: "Likes",
presets: [
%{label: "Over 100", values: fn -> %{"start" => 100, "end" => nil} end},
%{label: "1-99", values: fn -> %{"start" => 1, "end" => 99} end}
]
}
]
end
| Key | Required | Description |
|---|---|---|
:module | yes | The filter module |
:label | no | Overrides the module's label/0 |
:default | no | Pre-selected value on initial page load |
:presets | no | Quick-select shortcuts: [%{label: String.t(), values: (-> value)}] |
MyAppWeb.Filters.<Resource><FilterName> (e.g. MyAppWeb.Filters.PostPublished)lib/my_app_web/filters/<snake_case_name>.exfilters/0 must match the database column or foreign keyimport Ecto.Query when using dynamic/2 or writing custom queriesoptions/1 are fine since it runs at render timenpx claudepluginhub naymspace/backpexGenerates Backpex LiveResource modules for admin CRUD views with Ecto schemas, adapter config, fields, filters, and routing.
Provides Elixir Ecto patterns for schemas, changesets, queries, associations, and transactions. Useful for building database-driven Elixir applications.
Builds Ecto.Query DSL queries for where clauses, joins, aggregates, preloading associations, and composition in Elixir apps.