# `Masu.Column`
[🔗](https://github.com/hattoriai/masu/blob/v0.1.0/lib/masu/column.ex#L1)

A column of a grid: which value of a row it shows, how, and what a
person may do with it.

A grid makes its columns from its `:col` slots (see
`Masu.Components.data_grid/1`):

    <:col field={:name} />
    <:col field={:total} type={:decimal} label="Total" width={140} />
    <:col :let={order} field={:status} type={:enum}>
      <.badge status={order.status} />
    </:col>

## Types

The type says how the browser formats a value, in the grid's locale,
how a filter reads the value it is given, and where the cell aligns:

  * `:text` (the default) and `:enum`, as they are;
  * `:integer`, `:number` and `:decimal`, as numbers, aligned to the end
    of the cell. A decimal goes to the browser as a string, so no digit
    is lost on the way;
  * `:date`, `:datetime` and `:time`;
  * `:boolean`, as a check mark.

A column with an inner block is rendered by it, on the server, for each
row that the browser shows; the type still says how it sorts and
filters.

`type={:auto}` is a column whose type the grid learns from its values,
in the first block of rows of its source: integers make an `:integer`
column, `Decimal`s a `:decimal` one, `Date`s a `:date` one, and so on;
values of several types, or of none of these, make it `:text`. The
grid keeps the type until its source changes. A column whose rows are
a query tool's results, of no types, takes it.

## Rows as lists

`field={2}` reads the value at that place of a row that is a list (from
0): a query tool's rows, which come as lists of values in the order of
its columns. Its key is the place as a string unless given.

## Editing

In a grid that edits, `values` lists the values of an `:enum` column,
which its editor offers (a schema's `Ecto.Enum` field has them unless
given); `decimals` shows a `:decimal` or `:number` column with that
many digits after the point, whatever the value has.

## Layout

`hidden` starts the column hidden (a person shows it from the columns
menu), and `pinned={:start}` or `pinned={:end}` keeps it in view while
the others scroll sideways. See `Masu.Layout`.

## Totals

`aggregate={:sum}` totals the column in the row of each group and in a
row of totals at the bottom of the grid; see `Masu.Group`.

# `aggregate`

```elixir
@type aggregate() ::
  :sum | :avg | :min | :max | :count | :count_distinct | ([term()] -&gt; term())
```

How a column totals its values, in a group's row and the totals row:
`:sum`, `:avg`, `:min`, `:max`, `:count` (of the values that are not
`nil`), `:count_distinct`, or, for a list, a function of the rows.

# `t`

```elixir
@type t() :: %Masu.Column{
  aggregate: aggregate() | nil,
  align: :start | :center | :end,
  auto: map() | nil,
  creatable: boolean(),
  decimals: non_neg_integer() | nil,
  editable: boolean() | nil,
  editable_if: (term() -&gt; boolean()) | nil,
  field: atom() | String.t() | non_neg_integer() | nil,
  filter_ops: [Masu.Filter.op()] | nil,
  filterable: boolean(),
  hidden: boolean(),
  key: String.t(),
  label: String.t(),
  min_width: pos_integer(),
  pinned: :start | :end | nil,
  searchable: boolean(),
  slot: map() | nil,
  sortable: boolean(),
  type: type(),
  value: (term() -&gt; term()) | nil,
  values: [term()] | nil,
  width: pos_integer()
}
```

# `type`

```elixir
@type type() ::
  :text
  | :enum
  | :integer
  | :number
  | :decimal
  | :date
  | :datetime
  | :time
  | :boolean
```

# `editable?`

```elixir
@spec editable?(t()) :: boolean()
```

Whether a person may edit the column's cells: its grid edits (it has a
`changeset` or an `update`), the column names a field (not a `value`
function), and it does not say `editable={false}`. A column whose
`editable` is a function of the row edits the cells of the rows for
which it gives `true` (see `editable?/2`).

# `editable?`

```elixir
@spec editable?(t(), term()) :: boolean()
```

Whether a person may edit the column's cell of a row: the column edits
(`editable?/1`), and its `editable` function, if it has one, says so for
the row.

# `find`

```elixir
@spec find([t()], String.t()) :: t() | nil
```

Finds a column by its key.

# `get`

```elixir
@spec get(t(), term()) :: term()
```

The value of the column for a row.

# `infer`

```elixir
@spec infer([term()]) :: type()
```

The type of a column of these values: the type that every value which
is not `nil` has (an integer and a float make `:number`), else `:text`.

# `new`

```elixir
@spec new(map() | keyword()) :: t()
```

Makes a column from the attributes of a `:col` slot (or a keyword list
or map of the same names).

`field` names the value of a row (a key of a map or a field of a
struct); `value`, a function of the row, computes it instead. `key`
names the column on the wire and in `Masu.Test`; it is the field as a
string unless given. `label` is the field in words unless given.

Raises `ArgumentError` for a column with neither `field` nor `value`,
or with an unknown type.

# `stored?`

```elixir
@spec stored?(t()) :: boolean()
```

Whether the column's values can be sorted and filtered by a database:
it reads a field, not a function of the row.

# `typed`

```elixir
@spec typed(t(), type()) :: t()
```

A column of `type={:auto}` made again with a type (`infer/1`); any
other column as it is.

# `types`

```elixir
@spec types() :: [type()]
```

The types a column can have.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
