Skip to content

Commit

Permalink
Add Grid bulk action methods (#1920)
Browse files Browse the repository at this point in the history
  • Loading branch information
mhuser authored Sep 4, 2023
1 parent ede6eb5 commit 01ef91e
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 11 deletions.
37 changes: 31 additions & 6 deletions demos/collection/grid.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@

use Atk4\Data\Model;
use Atk4\Ui\Button;
use Atk4\Ui\Form;
use Atk4\Ui\Grid;
use Atk4\Ui\Js\Jquery;
use Atk4\Ui\Js\JsBlock;
use Atk4\Ui\Js\JsExpression;
use Atk4\Ui\Js\JsReload;
use Atk4\Ui\Js\JsToast;
Expand Down Expand Up @@ -71,12 +73,35 @@
// TODO button is added not only to the table rows, but also below the table!
// $grid->addExecutorButton($deleteExecutor, new Button(['icon' => 'times circle outline']));

$sel = $grid->addSelection();
$grid->menu->addItem('show selection')
->on('click', new JsExpression(
'alert(\'Selected: \' + [])',
[$sel->jsChecked()]
));
$grid->addSelection();

$grid->addBulkAction(['Show selected', 'icon' => 'binoculars'], static function (Jquery $j, array $ids) {
return new JsToast('Selected: ' . implode(', ', $ids) . '#');
});

// Executing a modal on a bulk selection
$grid->addModalBulkAction(['Delete selected', 'icon' => 'trash'], '', static function (View $modal, array $ids) use ($grid) {
Message::addTo($modal, [
'The selected records will be permanently deleted: ' . implode(', ', $ids) . '#',
'type' => 'warning',
'icon' => 'warning',
]);
$form = Form::addTo($modal);
$form->buttonSave->set('Delete');
$form->buttonSave->icon = 'trash';
$form->onSubmit(static function (Form $form) use ($grid, $ids) {
$grid->model->atomic(static function () use ($grid, $ids) {
foreach ($ids as $id) {
$grid->model->delete($id);
}
});

return new JsBlock([
$grid->jsReload(),
$form->jsSuccess(),
]);
});
});

// Setting ipp with an array will add an ItemPerPageSelector to paginator.
$grid->setIpp([10, 100, 1000]);
62 changes: 58 additions & 4 deletions src/Grid.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class Grid extends View
public $actionButtons;

/**
* Calling addAction will add a new column inside $table with dropdown menu,
* Calling addActionMenuItem will add a new column inside $table with dropdown menu,
* and will be re-used for next addActionMenuItem().
*
* @var Table\Column|null
Expand Down Expand Up @@ -386,7 +386,7 @@ private function getActionButtons(): Table\Column\ActionButtons
}

/**
* Similar to addAction. Will add Button that when click will display
* Similar to addActionButton. Will add Button that when click will display
* a Dropdown menu.
*
* @param View|string $view
Expand Down Expand Up @@ -498,8 +498,8 @@ public function addPopup($columnName, $popup = null, $icon = 'caret square down'
}

/**
* Similar to addAction but when button is clicked, modal is displayed
* with the $title and $callback is executed through VirtualPage.
* Similar to addActionButton but when button is clicked, modal is displayed
* with the $title and $callback is executed.
*
* @param string|array|View $button
* @param string $title
Expand All @@ -513,6 +513,60 @@ public function addModalAction($button, $title, \Closure $callback, $args = [])
return $this->getActionButtons()->addModal($button, $title, $callback, $this, $args);
}

/**
* @return list<string>
*/
private function explodeSelectionValue(string $value): array
{
return $value === '' ? [] : explode(',', $value);
}

/**
* Similar to addActionButton but apply to a multiple records selection and display in menu.
* When menu item is clicked, $callback is executed.
*
* @param string|array|MenuItem $item
* @param \Closure(Js\Jquery, list<string>): JsExpressionable $callback
* @param array $args extra URL argument for callback
*
* @return View
*/
public function addBulkAction($item, \Closure $callback, $args = [])
{
$menuItem = $this->menu->addItem($item);
$menuItem->on('click', function (Js\Jquery $j, string $value) use ($callback) {
return $callback($j, $this->explodeSelectionValue($value));
}, [$this->selection->jsChecked()]);

return $menuItem;
}

/**
* Similar to addModalAction but apply to a multiple records selection and display in menu.
* When menu item is clicked, modal is displayed with the $title and $callback is executed.
*
* @param string|array|MenuItem $item
* @param string $title
* @param \Closure(View, list<string>): void $callback
* @param array $args extra URL argument for callback
*
* @return View
*/
public function addModalBulkAction($item, $title, \Closure $callback, $args = [])
{
$modalDefaults = is_string($title) ? ['title' => $title] : []; // @phpstan-ignore-line

$modal = Modal::addTo($this->getOwner(), $modalDefaults);
$modal->set(function (View $t) use ($callback) {
$callback($t, $this->explodeSelectionValue($t->stickyGet($this->name) ?? ''));
});

$menuItem = $this->menu->addItem($item);
$menuItem->on('click', $modal->jsShow(array_merge([$this->name => $this->selection->jsChecked()], $args)));

return $menuItem;
}

/**
* Get sortBy value from URL parameter.
*/
Expand Down
2 changes: 1 addition & 1 deletion src/Table/Column/ActionButtons.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public function addButton($button, $action = null, string $confirmMsg = '', $isD
*/
public function addModal($button, $defaults, \Closure $callback, $owner = null, $args = [])
{
if ($owner === null) {
if ($owner === null) { // TODO explicit owner should not be needed
$owner = $this->getOwner()->getOwner();
}

Expand Down
23 changes: 23 additions & 0 deletions tests-behat/grid.feature
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,26 @@ Feature: Grid
Then I should see "Andorra"
Then I should see "China"
Then I should see "Zambia"

Scenario: Bulk action
Given I am on "collection/grid.php"
Then I press button "Show selected"
Then Toast display should contain text "Selected: #"
When I click using selector "//tr[5]//div.ui.checkbox"
When I click using selector "//tr[8]//div.ui.checkbox"
Then I press button "Show selected"
Then Toast display should contain text "Selected: 5, 8#"

Scenario: Bulk modal action
Given I am on "collection/grid.php"
Then I press button "Delete selected"
Then Modal is open with text "The selected records will be permanently deleted: #"
Then I press button "Delete"
Then I should see "Success"
Then I click close modal
When I click using selector "//tr[5]//div.ui.checkbox"
When I click using selector "//tr[8]//div.ui.checkbox"
Then I press button "Delete selected"
Then Modal is open with text "The selected records will be permanently deleted: 5, 8#"
Then I press button "Delete"
Then I should see "Success"

0 comments on commit 01ef91e

Please sign in to comment.