Skip to content

Commit

Permalink
Allow disabling table row action button
Browse files Browse the repository at this point in the history
  • Loading branch information
ibelar committed Jun 26, 2024
1 parent b170fec commit 0563a8c
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 16 deletions.
26 changes: 11 additions & 15 deletions src/Component/Table.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
use Fohn\Ui\Js\JsRenderInterface;
use Fohn\Ui\Js\Type\ArrayLiteral;
use Fohn\Ui\Js\Type\Integer;
use Fohn\Ui\Js\Type\ObjectLiteral;
use Fohn\Ui\Js\Type\Variable;
use Fohn\Ui\Service\Ui;
use Fohn\Ui\Tailwind\Tw;
Expand Down Expand Up @@ -91,9 +90,6 @@ class Table extends View implements VueInterface

public string $idColumnName = 'id';

/** @var array<string, JsFunction> An array of table action */
protected array $actions = [];

protected ?Data $tableDataCb = null;

protected string $payloadClass = Payload::class;
Expand Down Expand Up @@ -218,23 +214,24 @@ public function addActionColumn(string $columnName, string $actionName, View\But
['template' => Ui::templateFromFile('vue-component/table/column/header-empty.html')]
);
}
/** @var Column\Action $actionColumn */
$actionColumn = Column\Action::factory(['columnHeader' => $header])->alignText('center');

$this->addColumn(
$columnName,
Column\Action::factory(
[
'columnHeader' => $header,
]
)->alignText('center')
$actionColumn
);
} else {
/** @var Column\Action $actionColumn */
$actionColumn = $this->getTableColumn($columnName);
}

$button->setViewName($actionName);
static::bindVueAttr($button, 'disabled', "cell?.state?.{$actionName} || false");
static::bindVueEvent($button, $eventName, "executeRowAction('{$actionName}', cell)");
$column = $this->getTableColumn($columnName);
$column->addView($button);

$this->actions[$actionName] = JsFunction::arrow([Variable::set('cell')]);
$actionColumn->addView($button);

return $this->actions[$actionName];
return $actionColumn->addRowActionFn($actionName, JsFunction::arrow([Variable::set('cell')]));
}

public function addFilter(Filter $filter, string $regionName = self::FILTER_REGION_NAME): Filter
Expand Down Expand Up @@ -377,7 +374,6 @@ private function renderTableProps(): void
$this->getTemplate()->setJs('columns', ArrayLiteral::set($this->getColumnsDefinition()));
$this->getTemplate()->setJs('itemsPerPage', Integer::set($this->paginatorItemsPerPage));
$this->getTemplate()->setJs('itemsPerPages', ArrayLiteral::set($this->paginatorItemsPerPages));
$this->getTemplate()->setJs('tableRowActions', ObjectLiteral::set($this->actions));
}

private function getColumnsDefinition(): array
Expand Down
53 changes: 53 additions & 0 deletions src/Component/Table/Column/Action.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,71 @@

namespace Fohn\Ui\Component\Table\Column;

use Fohn\Ui\Component\Table;
use Fohn\Ui\Js\JsFunction;
use Fohn\Ui\Js\Type\ObjectLiteral;
use Fohn\Ui\View;

class Action extends Generic implements ActionInterface
{
public const HOOK_DISABLED = self::class . '@action:enable';

public string $defaultTemplate = 'vue-component/table/column/action.html';

/** @var array<string, JsFunction> Column action may contain more than one row action as js function. */
protected array $rowActions = [];

public function getRowActions(): array
{
return $this->rowActions;
}

public function renderInTableTemplate(Table $table): void
{
parent::renderInTableTemplate($table);

$table->getTemplate()->setJs('tableRowActions', ObjectLiteral::set($this->rowActions));
}

protected function beforeHtmlRender(): void
{
$this->clearIdAttribute($this);
parent::beforeHtmlRender();
}

/**
* Callback function in order to determine if a row action button should be disabled or not.
* The closure function will receive to record of the row being evaluated.
* The closure function should return true if disabling is need.
*
* Suppose you have a column name 'action' that contains an action name call 'edit' and
* you would like to disable the action base on row value.
* You can disable the button assign to the action name 'edit' this way:
* $table->getTableColumn('action')->disableActionName('edit', static function ($rowValue) {
* return true or false;
* });
*/
public function disableActionName(string $actionName, \Closure $fx): self
{
$this->onHook(static::HOOK_DISABLED, static function (string $name, array $rowValue) use ($actionName, $fx): bool {
$return = false;
if ($actionName === $name) {
$return = $fx($rowValue);
}

return $return;
});

return $this;
}

public function addRowActionFn(string $name, JsFunction $fn): JsFunction
{
$this->rowActions[$name] = $fn;

return $fn;
}

/**
* Action column content is duplicate within each row of a table,
* therefore, make sure that each Views inside column has the Id
Expand Down
12 changes: 11 additions & 1 deletion src/Component/Table/Result/Set.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,18 @@ public function outputData(array $columns, string $idColumnName): array
$rowTws = $this->table->callHook(Table::HOOK_ROW_TW, HookFn::withTw([(string) $id, (object) $row]));
$cells = [];
foreach ($columns as $name => $column) {
$attr = [];
$value = null;
$cellTws = null;
if (!$column instanceof Column\ActionInterface) {
if ($column instanceof Column\Action) {
// @var Column\Action $column
// call hook function with row value and actionName as params. Callback must return a boolean.
foreach ($column->getRowActions() as $action => $fn) {
$attr[$action] = $column->callHook(Column\Action::HOOK_DISABLED, HookFn::withTypeFn(static function ($fn, $args): bool {
return $fn(...$args);
}, [$action, $row]));
}
} else {
$value = $column->getDisplayValue($row[$name], $id);
// call hook function with cell value as params. Callback must return a Tw object.
$cellTws = $column->callHook(Column::HOOK_CELL_TW, HookFn::withTw([$row[$name]]));
Expand All @@ -59,6 +68,7 @@ public function outputData(array $columns, string $idColumnName): array
'name' => $column->getColumnName(),
'value' => $value,
'css' => $cellTws !== null ? $cellTws->toString() : '',
'state' => $attr,
];
}
$results['rows'][] = ['id' => (string) $id, 'cells' => $cells, 'css' => $rowTws->toString()];
Expand Down

0 comments on commit 0563a8c

Please sign in to comment.