Editing Data โ
Introduction โ
editOnClick() and toggleable() are plugins. They render in the cell and dispatch updates to onPluginUpdated(). They do not auto-save: you persist the value yourself, so they work with any datasource.
Edit on click โ
Clicking a cell turns it into a contenteditable input. Enter submits. Escape discards. If the value is empty, a fallback can be shown.
Chain editOnClick() on a Column:
use PowerComponents\LivewirePowerGrid\PowerGridComponent;
use PowerComponents\LivewirePowerGrid\Column;
class ProductTable extends PowerGridComponent
{
public function columns(): array
{
return [
Column::add()
->title('Name')
->field('name')
->editOnClick(
hasPermission: auth()->check(),
fallback: '- empty -'
),
];
}
}If the column displays a custom field, the second argument to field() (or editOnClick(dataField:)) must be the database column that is saved:
use PowerComponents\LivewirePowerGrid\PowerGridComponent;
use PowerComponents\LivewirePowerGrid\Column;
use PowerComponents\LivewirePowerGrid\Facades\PowerGrid;
use PowerComponents\LivewirePowerGrid\PowerGridFields;
use Illuminate\Support\Number;
class ProductTable extends PowerGridComponent
{
public function fields(): PowerGridFields
{
return PowerGrid::fields()
->add('id')
->add('price')
->add('price_in_eur', function ($product) {
return Number::currency($product->price, in: 'EUR');
});
}
public function columns(): array
{
return [
Column::add()
->title('Price (EUR)')
->field('price_in_eur', 'price')
->editOnClick(
hasPermission: auth()->check(),
fallback: 'โฌ0,00'
),
];
}
}| Parameter | Description | Default |
|---|---|---|
| (bool) $hasPermission | When true, the cell is editable. | true |
| (string) $dataField | Field used as the editor value. Sets the column dataField when filled. | '' |
| (?string) $fallback | Fallback text for empty values. | null |
| (bool) $saveOnMouseOut | If true, submit when clicking outside the input. | false |
Toggleable โ
The cell becomes a switch for a boolean. Without permission, a Yes/No badge is shown instead.
Relationship fields (field contains .) are not rendered as a switch.
use PowerComponents\LivewirePowerGrid\PowerGridComponent;
use PowerComponents\LivewirePowerGrid\Column;
class ProductTable extends PowerGridComponent
{
public function columns(): array
{
return [
Column::add()
->title('In Stock')
->field('in_stock')
->toggleable(
hasPermission: auth()->check(),
trueLabel: 'Yes',
falseLabel: 'No'
),
];
}
}| Parameter | Description | Default |
|---|---|---|
| (bool) $hasPermission | Enable or disable the switch | true |
| (string) $trueLabel | Label when the value is true | Yes |
| (string) $falseLabel | Label when the value is false | No |
Handling updates โ
Editable and Toggleable call only onPluginUpdated(). Validate input before persisting.
| Parameter | Type | Description |
|---|---|---|
$plugin | 'editable' | 'toggleable' | string | Plugin that triggered the event. |
$event | string | 'updated' for editable and toggleable. |
$params | array{id: string, field: string, value: string} | Record ID (as string), column dataField, and submitted value. |
use App\Models\Product;
use PowerComponents\LivewirePowerGrid\PowerGridComponent;
class ProductTable extends PowerGridComponent
{
public function onPluginUpdated(string $plugin, string $event, array $params): void
{
if ($plugin === 'editable' || $plugin === 'toggleable') {
Product::query()->find($params['id'])->update([
$params['field'] => $params['value'],
]);
}
}
}onUpdatedEditable() and onUpdatedToggleable() remain as deprecated helpers that forward to onPluginUpdated(). The plugins never call them, so overriding them has no effect.
Updating custom fields โ
$params['field'] is the column's dataField (the field() value when no data field is set). If a custom field is edited without a data field (e.g. Column::make('Price', 'price_formatted')), the editor shows and submits the formatted value. Map it back and parse it before saving:
use PowerComponents\LivewirePowerGrid\PowerGridComponent;
use App\Models\Product;
class ProductTable extends PowerGridComponent
{
public function onPluginUpdated(string $plugin, string $event, array $params): void
{
if ($plugin !== 'editable') {
return;
}
$field = $params['field'];
$value = $params['value'];
if ($field === 'price_formatted') {
$field = 'price';
$value = str($value)->replace('.', '')
->replace(',', '.')
->replaceMatches('/[^Z0-9\.]/', '')
->toString();
}
Product::query()->find($params['id'])->update([
$field => $value,
]);
}
}Reload data on update โ
Call $this->fetchDatasource() after a successful write if you need a full datasource refresh:
use PowerComponents\LivewirePowerGrid\PowerGridComponent;
use App\Models\Product;
class ProductTable extends PowerGridComponent
{
public function onPluginUpdated(string $plugin, string $event, array $params): void
{
$updated = Product::query()->find($params['id'])->update([
$params['field'] => $params['value'],
]);
if ($updated) {
$this->fetchDatasource();
}
}
}Reload data from another component โ
Set a unique table name, then dispatch pg:eventRefresh-{tableName}:
namespace App\Livewire;
use Livewire\Component;
class SomeComponent extends Component
{
public function save()
{
$this->dispatch('pg:eventRefresh-ProductTable');
}
}Skip re-render after update โ
Call Livewire's skipRender() after the update:
use PowerComponents\LivewirePowerGrid\PowerGridComponent;
use App\Models\Product;
class ProductTable extends PowerGridComponent
{
public function onPluginUpdated(string $plugin, string $event, array $params): void
{
Product::query()->where('id', $params['id'])->update([
$params['field'] => $params['value'],
]);
$this->skipRender();
}
}