Backpex.Filter behaviour (Backpex v0.18.0)

Copy Markdown View Source

The base behaviour for all filters. Injects also basic layout, form and delete button for a filters rendering.

Validation

Filters support changeset-based validation to ensure that URL parameters are validated before being applied to queries. Each filter module can implement the changeset/3 callback to apply custom validations, or rely on the default implementation which uses type/1.

Implementing a Custom Filter

When implementing a custom filter, you should:

  1. Implement type/1 to return the Ecto type for your filter's value
  2. Optionally implement changeset/3 for custom validations
  3. Implement query/4 which receives the already-validated and casted values

Example

defmodule MyFilter do
  use Backpex.Filter

  @impl Backpex.Filter
  def type(_assigns), do: :integer

  @impl Backpex.Filter
  def changeset(changeset, field, _assigns) do
    changeset
    |> Ecto.Changeset.validate_number(field, greater_than: 0)
  end

  @impl Backpex.Filter
  def query(query, field, value, _assigns) do
    Ecto.Query.where(query, [x], field(x, ^field) == ^value)
  end
end

Summary

Callbacks

Defines whether the filter can be used or not.

Applies validation to the changeset for this filter's field.

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.

Returns the Ecto type for this filter's value.

Public validation API for testing and programmatic validation.

Callbacks

can?(assigns)

@callback can?(Phoenix.LiveView.Socket.assigns()) :: boolean()

Defines whether the filter can be used or not.

changeset(t, atom, assigns)

@callback changeset(Ecto.Changeset.t(), atom(), assigns :: map()) :: Ecto.Changeset.t()

Applies validation to the changeset for this filter's field.

Called during changeset building. The default implementation simply returns the changeset unchanged (relying on type casting). Override this to add custom validations.

Parameters

  • changeset - The Ecto changeset being built
  • field - The atom key for this filter
  • assigns - Socket assigns for context

Examples

def changeset(changeset, field, _assigns) do
  changeset
  |> Ecto.Changeset.validate_inclusion(field, ["active", "inactive"])
end

label()

(optional)
@callback label() :: String.t()

If no label is defined on the filter map, this value is used as the filter label.

query(t, any, any, assigns)

@callback query(Ecto.Query.t(), any(), any(), assigns :: map()) :: Ecto.Query.t()

The filter query that is executed if an option was selected.

The value parameter contains the already-validated and casted value from the changeset.

render(assigns)

Renders the filters selected value(s).

render_form(assigns)

Renders the filters options form.

type(assigns)

@callback type(assigns :: map()) :: atom() | tuple()

Returns the Ecto type for this filter's value.

Used to build schemaless changesets for validation. Common types include:

  • :string - for single value select filters
  • {:array, :string} - for multi-select or boolean filters
  • :map - for range filters with start/end values

Examples

def type(_assigns), do: :string
def type(_assigns), do: {:array, :string}
def type(_assigns), do: :map

validate(value, assigns)

@callback validate(value :: any(), assigns :: map()) :: {:ok, any()} | {:error, keyword()}

Public validation API for testing and programmatic validation.

Returns {:ok, casted_value} on success or {:error, errors} on failure. The default implementation builds a mini-changeset and validates it.

Parameters

  • value - The raw value to validate
  • assigns - Socket assigns for context

Examples

iex> MyFilter.validate("active", %{})
{:ok, "active"}

iex> MyFilter.validate("invalid", %{})
{:error, [value: {"is invalid", []}]}