View Source Backpex.Filter behaviour (Backpex v0.1.1)

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:

  1. Add modules implementing one of the behaviors from the Backpex.Filters namespace 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.
  1. Implement the filters/0 callback 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 label/0, 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
end

Filter 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:

  1. :label – simply the String shown to the user
  2. :values – a function with arity 0 that returns the values corresponding to your used filter

See the example below for :values return values for the default range and boolean filter

@impl Backpex.LiveResource
def filters, do: [
    begins_at: %{
      module: MyAppWeb.Filters.DateRange,
      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.

The filter's 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()

The filter's label.

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

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

Renders the filters selected value(s).

Renders the filters options form.