0

I've created a grid via ui component with a mass action. I've also added a selections column so when the user click on one or more checkboxes, the items in the grid get selected and the mass action can be called on those items.

This work if the user selects only some records from the list, but if the user selects all the items by the action dropdown "select all", then the mass action cannot work.

This is because different parameters are used: - when the user checks the boxes individually, then the "selected" parameter is passed to my controller with the id selected - when the user chooses "select all", no "selected" parameter is passed. Instead, there is a parameter "excluded" false and no ids are passed to my controller.

Magento doesn't need the ids when "select all" is chosen because the mass action simply loads the collection. My problem is that my grid is not related to a table, so I cannot call any model/collection. I have a custom data provider that gets the data from an external source and displays the data in the grid.

Calling the external data all over again in the mass action controller is far more expensive than simply passing the ids, so simulating the magento way of reloading the collection is not a desirable option. The best thing in my opinion would be to pass the "selected" parameter also when all items are selected with the "select all" dropdown option.

Is there a way to achive this?

My code is pretty standard:

  • the mass action and the grid is build via ui component listing:
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
...
<listingToolbar name="listing_top">
  <massaction name="listing_massaction">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="selectProvider" xsi:type="string">my_provider.ids</item>
                    <item name="indexField" xsi:type="string">id</item>
                </item>
            </argument>
            <action name="massaction_name">
                <argument name="data" xsi:type="array">
                    <item name="config" xsi:type="array">
                        <item name="type" xsi:type="string">massaction_name</item>
                        <item name="label" xsi:type="string" translate="true">Mass Action Name</item>
                        <item name="url" xsi:type="url" path="route/controller/path"/>
                        <item name="confirm" xsi:type="array">
                            <item name="title" xsi:type="string" translate="true">Title</item>
                            <item name="message" xsi:type="string" translate="true">Are you sure?</item>
                        </item>
                    </item>
                </argument>
            </action>
        </massaction>
...
<columns name="my_provider_columns">
   <column name="ids">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="indexField" xsi:type="string">id</item>
                    <item name="dataType" xsi:type="string">select</item>
                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/onoff</item>
                </item>
            </argument>
        </column>
...
  • the controller retrieves the request parameters:
...
class Path extends Action implements HttpGetActionInterface, HttpPostActionInterface
...
public function execute() {
  $params = $this->getRequest()->getParams();
}
...

As I mentioned, $params returns an array "selected" with the ids or a flag set to false if "selectAll" was used for the selection:

array (
  'selected' => 
  array (
    0 => '505928',
...
array (
  'excluded' => 'false'
...

But I need the "selected" array also when the selectAll option is used. Is there a way to get it?

0

Update your listing file

    <massaction name="listing_massaction" component="Magento_Ui/js/grid/tree-massactions">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="selectProvider" xsi:type="string">your_custom_listing.your_custom_listing.my_provider_columns.ids</item>
                <item name="component" xsi:type="string">Magento_Ui/js/grid/tree-massactions</item>
                <item name="indexField" xsi:type="string">id</item>
            </item>
        </argument>
        <action name="is_delete">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="type" xsi:type="string">delete</item>
                    <item name="label" xsi:type="string" translate="true">Delete</item>
                    <item name="url" xsi:type="url" path="your_admin_route_name/your_admin_contoller_name/massDelete">
                    </item>
                    <item name="confirm" xsi:type="array">
                        <item name="title" xsi:type="string" translate="true">Delete items</item>
                        <item name="message" xsi:type="string" translate="true">Are you sure you wan't to delete selected items?</item>
                    </item>
                </item>
            </argument>
        </action>
    </massaction>

And your mass delete file is here

<?php

namespace VendoreName\ModuleName\Controller\Adminhtml\YourContollerName;

use VendoreName\ModuleName\Model\ResourceModel\YourModelName\CollectionFactory;
use VendoreName\ModuleName\Model\YourModelNameFactory;
use Magento\Backend\App\Action\Context;
use Magento\Framework\Controller\ResultFactory;
use Magento\Ui\Component\MassAction\Filter;

class MassDelete extends \Magento\Backend\App\Action
{
    protected $filter;
    protected $collectionFactory;
    protected $CustomeModel;

    public function __construct(
        Context $context,
        Filter $filter,
        CollectionFactory $collectionFactory,
        YourModelNameFactory $CustomeModel
    ) {
        $this->filter = $filter;
        $this->collectionFactory = $collectionFactory;
        $this->CustomeModel = $CustomeModel;
        parent::__construct($context);
    }

    public function execute()
    {
        $CustomData = $this->collectionFactory->create();
        foreach ($CustomData as $value) {
            $templateId[] = $value['id'];
        }
        $parameterData = $this->getRequest()->getParams('id');
        $selectedAppsid = $this->getRequest()->getParams('id');
        if (array_key_exists("selected", $parameterData)) {
            $selectedAppsid = $parameterData['selected'];
        }
        if (array_key_exists("excluded", $parameterData)) {
            if ($parameterData['excluded'] == 'false') {
                $selectedAppsid = $templateId;
            } else {
                $selectedAppsid = array_diff($templateId, $parameterData['excluded']);
            }
        }
        $collection = $this->collectionFactory->create();
        $collection->addFieldToFilter('id', ['in' => $selectedAppsid]);
        $delete = 0;
        $model = [];
        foreach ($collection as $item) {
            $this->deleteById($item->getId());
            $delete++;
        }
        $this->messageManager->addSuccess(__('A total of %1 Records have been deleted.', $delete));
        $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
        return $resultRedirect->setPath('*/*/');
    }

    public function deleteById($id)
    {
        $item = $this->CustomeModel->load($id);
        $item->delete();
    }
}

I Hope This Helps You.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.