Skip to content

CheckboxColumn

A checkbox in the table: the value is saved when it is ticked or unticked. It behaves like ToggleColumn, only the control differs.

use Anvil\Collection\Columns\CheckboxColumn;
// in form()
Toggle::make('is_paid'),
// in collection()
CheckboxColumn::make('is_paid')->label('Paid'),
CheckboxColumn::make('is_shipped')->disabledWhen(fn ($record) => ! $record->is_paid),
Option Meaning
disabledWhen(fn ($record) => …) records whose value cannot be changed here; they show the value without a control
refreshesList() reloads the list after saving, see After saving

The column also takes the options of every column and the display options of TextColumn, which apply where the value is shown without a control.

The field saves 1 or 0. Without a control and in exports the value is shown like TextColumn::boolean(): a check or a cross, “Yes” or “No” in exports.

The column needs a writable Toggle of the same name in the form of the resource. It takes its rules and conversion from there, so the table and the form cannot differ. Without a matching field the column throws a LogicException, also with state() or queryColumn(), for virtual fields and for the state column of a workflow: only transitions change a state.

Saving goes through the component endpoint like a saved form:

  • Permissions: <slug>.update, the policies of the record and locked workflow states. Users who may not change the record see the value without a control.
  • disabledWhen() is checked again when saving.
  • Scope of the resource: records of other tenants are not found.
  • Only this column: it has its own action, other values in the request are not written.
  • Rules: those of the field and the validation of the model.
  • Audit log: the change gets an entry. A value that did not change is not written.
  • Rejected value: the message appears in the cell, the checkbox goes back to the stored value.
  • Changed by someone else: if the value is not the one that was shown when the list was loaded, nothing is written and the cell asks to reload the list. Changes to other columns of the record are no conflict.

Only the cell is updated. Other columns and the colour of the row show the change after the next load; refreshesList() reloads the list at once. The list is always reloaded when it is sorted or grouped by this column, because the row can move. Reloading clears the selection of records.

  • Cards and related lists show the value without a control.
  • updateRecord() and afterSave() of the resource are not called, because they expect the values of the whole form. Override Resource::updateColumn() for checks across fields and side effects:
public function updateColumn(array|object $record, string $column, mixed $value): void
{
parent::updateColumn($record, $column, $value);
if ($column === 'is_paid') {
service('notifier')->changed($record, $value);
}
}