LiveFilter.Field protocol (LiveFilter v0.1.0)

View Source

Protocol for defining custom field types in LiveFilter.

This protocol allows users to define completely custom field types with their own conversion logic, operators, and validation rules. It's entirely optional - users can work with LiveFilter without ever implementing this protocol.

Example Implementation

defmodule MyApp.PriorityField do
  defstruct [:levels, :default]

  def new(opts \ []) do
    %__MODULE__{
      levels: Keyword.get(opts, :levels, [:low, :medium, :high, :urgent]),
      default: Keyword.get(opts, :default, :medium)
    }
  end
end

defimpl LiveFilter.Field, for: MyApp.PriorityField do
  def to_filter_value(%{levels: levels}, ui_value) do
    # Convert UI selection to filter value
    case ui_value do
      "urgent_only" -> [:urgent]
      "high_and_up" -> [:high, :urgent]
      level when level in levels -> [level]
      _ -> nil
    end
  end

  def to_ui_value(_, filter_value) do
    # Convert filter value back to UI representation
    case filter_value do
      [:urgent] -> "urgent_only"
      [:high, :urgent] -> "high_and_up"
      [level] -> level
      _ -> nil
    end
  end

  def default_operator(_), do: :in

  def validate(%{levels: levels}, value) do
    if Enum.all?(value, &(&1 in levels)) do
      :ok
    else
      {:error, "Invalid priority level"}
    end
  end

  def operators(_) do
    [:in, :not_in, :equals]
  end

  def ui_component(_) do
    :custom_priority_selector
  end
end

Summary

Types

t()

All the types that implement this protocol.

Functions

Get the default operator for this field type.

Get available operators for this field type.

Convert a UI value (from form input, API, etc.) to a filter value.

Convert a filter value back to UI representation.

Get the suggested UI component for this field type.

Validate a value for this field type.

Types

t()

@type t() :: term()

All the types that implement this protocol.

Functions

default_operator(field_type)

@spec default_operator(t()) :: atom()

Get the default operator for this field type.

Used when creating filters without an explicit operator.

Parameters

  • field_type - The field type struct

Returns

An atom representing the default operator (e.g., :equals, :contains, :in)

operators(field_type)

@spec operators(t()) :: [atom()]

Get available operators for this field type.

Parameters

  • field_type - The field type struct

Returns

List of operator atoms that are valid for this field type.

to_filter_value(field_type, ui_value)

@spec to_filter_value(t(), any()) :: any() | nil

Convert a UI value (from form input, API, etc.) to a filter value.

This function handles the transformation from user input to the internal filter representation.

Parameters

  • field_type - The field type struct
  • ui_value - The value from the UI/form

Returns

The transformed value suitable for use in a LiveFilter.Filter struct, or nil if the value should be ignored.

to_ui_value(field_type, filter_value)

@spec to_ui_value(t(), any()) :: any()

Convert a filter value back to UI representation.

This is the inverse of to_filter_value/2 and is used when restoring UI state from URL parameters or saved filters.

Parameters

  • field_type - The field type struct
  • filter_value - The value from a LiveFilter.Filter

Returns

The value suitable for display/selection in the UI.

ui_component(field_type)

@spec ui_component(t()) :: atom() | map()

Get the suggested UI component for this field type.

This is just a hint - the actual UI implementation can use any component.

Parameters

  • field_type - The field type struct

Returns

An atom identifying the suggested component type, or a map with component details.

validate(field_type, value)

@spec validate(t(), any()) :: :ok | {:error, String.t()}

Validate a value for this field type.

Parameters

  • field_type - The field type struct
  • value - The value to validate

Returns

  • :ok if valid
  • {:error, reason} if invalid