Cardbox.FieldType behaviour (Cardbox v0.2.0)

Copy Markdown View Source

A type of field of your app's own: what its values are, how they are checked, how they compare and how they read.

defmodule MyApp.Cardbox.Rating do
  @behaviour Cardbox.FieldType

  @impl true
  def name, do: "rating"

  @impl true
  def kind(_options), do: :number

  @impl true
  def cast(value, _field, _opts) when value in 1..5, do: {:ok, value}
  def cast(value, _field, _opts), do: {:error, "is from 1 to 5, got: #{inspect(value)}"}
end

and in your config, beside Cardbox's own types:

config :cardbox, types: [MyApp.Cardbox.Rating]

The types are your app's config, not your Cardbox module's: a value is read in many places that know only its field (a filter, a table's column, a board's card, the JSON Schema an agent reads), as Kotoba's nodes are. A type's name is never one of Cardbox's (Cardbox.Type).

What a type says

Only name/0 and cast/3 are required; the others have defaults.

  • kind/1: how values compare, for filters and sorts (Cardbox.Type.kind/1): :text by default. A :list does not sort or group.
  • check_options/3: the field's options, checked when the field is added or changed, with the collection, so that an option may name another field. By default a type takes no options.
  • cast/3: a value given, checked, as it is kept (JSON): {:ok, nil} for an empty one.
  • load/2: a value kept, read for Elixir (Cardbox.get/3). As it is by default.
  • plain/2: a value as plain words or numbers: what a table sorts and shows, what Cardbox.Record.to_map/2 gives, and what a field that changes type converts. As it is by default.
  • text/2: a value in words for a person, in a table's cell and on a board's card. plain/2's, as text, by default.
  • operators/1: the filter operators, those of its kind by default.
  • json_schema/1: the JSON Schema of a value, for agents. A string by default.
  • words/2: the words of a value in the record's search text. None by default.

Summary

Functions

The app's types (config :cardbox, types: [...]), by name.

The app's type of a name, or nil (one of Cardbox's, or none).

Callbacks

cast(value, t, opts)

@callback cast(value :: term(), Cardbox.Field.t(), opts :: keyword()) ::
  {:ok, term()} | {:error, String.t()}

check_options(options, previous, t)

(optional)
@callback check_options(options :: map(), previous :: map(), Cardbox.Collection.t()) ::
  {:ok, map()} | {:error, String.t()}

json_schema(t)

(optional)
@callback json_schema(Cardbox.Field.t()) :: map()

kind(options)

(optional)
@callback kind(options :: map()) :: Cardbox.Type.kind()

load(value, t)

(optional)
@callback load(value :: term(), Cardbox.Field.t()) :: term()

name()

@callback name() :: String.t()

operators(t)

(optional)
@callback operators(Cardbox.Field.t()) :: [atom()]

plain(value, t)

(optional)
@callback plain(value :: term(), Cardbox.Field.t()) :: term()

text(value, t)

(optional)
@callback text(value :: term(), Cardbox.Field.t()) :: String.t() | nil

words(value, t)

(optional)
@callback words(value :: term(), Cardbox.Field.t()) :: [String.t()]

Functions

all()

@spec all() :: %{required(String.t()) => module()}

The app's types (config :cardbox, types: [...]), by name.

get(name)

@spec get(String.t() | nil) :: module() | nil

The app's type of a name, or nil (one of Cardbox's, or none).