Magento 2: Grid mass action provides collection of Magento\Framework\View\Element\UiComponent\DataProvider\Document instead of models

magento.stackexchange https://magento.stackexchange.com/questions/135881

Question

I'm trying to make a mass delete action for my custom grid. A very helpful source of examples is this grid sample module by Marius but still I can't find the reason why the grid pass collection of Documents instead actual collection of models.

My mass action declaration in the grid ui component:

<argument name="data" xsi:type="array">
    <item name="js_config" xsi:type="array">
        <item name="provider" xsi:type="string">fields_grid.fields_grid_data_source</item>
        <item name="deps" xsi:type="string">fields_grid.fields_grid_data_source</item>
        <!--Declare the data source name which will be defined below-->
    </item>
    <item name="spinner" xsi:type="string">vendor_modulename_columns</item>
    <!--Declare the listing of columns which will be defined below-->
    <item name="buttons" xsi:type="array">
        <item name="add" xsi:type="array">
            <item name="name" xsi:type="string">add</item>
            <item name="label" xsi:type="string" translate="true">Add New Field</item>
            <item name="class" xsi:type="string">primary</item>
            <item name="url" xsi:type="string">*/field/newfield</item>
        </item>
        <!--The button on the top of the Grid-->
    </item>
</argument>
<dataSource name="fields_grid_data_source">
    <!--The data source-->
    <argument name="dataProvider" xsi:type="configurableObject">
        <argument name="class" xsi:type="string">Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider</argument>
        <argument name="name" xsi:type="string">fields_grid_data_source</argument>
        <argument name="primaryFieldName" xsi:type="string">id</argument>
        <argument name="requestFieldName" xsi:type="string">id</argument>
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="component" xsi:type="string">Magento_Ui/js/grid/provider</item>
                <item name="update_url" xsi:type="url" path="mui/index/render"/>
                <item name="storageConfig" xsi:type="array">
                    <item name="indexField" xsi:type="string">id</item>
                </item>
            </item>
        </argument>
    </argument>
</dataSource>
<massaction name="listing_massaction">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="selectProvider" xsi:type="string">fields_grid.fields_grid.vendor_modulename_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="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="*/field/massdelete"/>
                    <item name="confirm" xsi:type="array">
                        <item name="title" xsi:type="string" translate="true">Delete fields</item>
                        <item name="message" xsi:type="string" translate="true">Are you sure to delete selected fields?</item>
                    </item>
                </item>
            </argument>
        </action>
    </massaction> 

And the mass action controller:

<?php

namespace Vendor\ModuleName\Controller\Adminhtml\Field;

use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Registry;
use Magento\Framework\Stdlib\DateTime\Filter\Date;
use Magento\Framework\View\Result\PageFactory;
use Magento\Ui\Component\MassAction\Filter;
use Vendor\ModuleName\Api\FieldRepositoryInterface;
use Vendor\ModuleName\Controller\Adminhtml\Field;
use Vendor\ModuleName\Model\Field as FieldModel;
use Vendor\ModuleName\Model\ResourceModel\Field\CollectionFactory;

abstract class MassAction extends Field
{
    /**
     * @var Filter
     */
    protected $filter;
    /**
     * @var CollectionFactory
     */
    protected $collectionFactory;
    /**
     * @var string
     */
    protected $successMessage;
    /**
     * @var string
     */
    protected $errorMessage;
    /**
     * @param Registry $registry
     * @param FieldRepositoryInterface $fieldRepository
     * @param PageFactory $resultPageFactory
     * @param Date $dateFilter
     * @param Context $context
     * @param Filter $filter
     * @param CollectionFactory $collectionFactory
     * @param $successMessage
     * @param $errorMessage
     */
    public function __construct(
        Registry $registry,
        FieldRepositoryInterface $fieldRepository,
        PageFactory $resultPageFactory,
        Date $dateFilter,
        Context $context,
        Filter $filter,
        CollectionFactory $collectionFactory,
        $successMessage,
        $errorMessage
    ) {
        $this->filter            = $filter;
        $this->collectionFactory = $collectionFactory;
        $this->successMessage    = $successMessage;
        $this->errorMessage      = $errorMessage;
        parent::__construct($registry, $resultPageFactory, $dateFilter, $context, $fieldRepository);
    }
    /**
     * @param FieldModel $field
     * @return mixed
     */
    protected abstract function massAction(FieldModel $field);
    /**
     * execute action
     *
     * @return \Magento\Backend\Model\View\Result\Redirect
     */
    public function execute()
    {
        try {
            $collection = $this->filter->getCollection($this->collectionFactory->create());
            $collectionSize = $collection->getSize();
            foreach ($collection as $field) {


                $this->massAction($field);  // <-- here lies the problem, $collection contains documents instead of Models



            }
            $this->messageManager->addSuccessMessage(__($this->successMessage, $collectionSize));
        } catch (LocalizedException $e) {
            $this->messageManager->addErrorMessage($e->getMessage());
        } catch (\Exception $e) {
            $this->messageManager->addExceptionMessage($e, __($this->errorMessage));
        }
        $redirectResult = $this->resultRedirectFactory->create();
        $redirectResult->setPath('Vendor_ModuleName/index/index');
        return $redirectResult;
    }
}

var_dump($collection->toArray()); returns correct array of elements which have been selected

What are the possible faults that cause this sort problem?

Was it helpful?

Solution

You should create a VirtualType in di.xml and type should be link to grid\collection

<virtualType name="Training\ComputerGame\Model\ResourceModel\ComputerGame\Grid\Collection" type="Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult">
    <arguments>
        <argument name="mainTable" xsi:type="string">computer_games</argument>
        <argument name="resourceModel" xsi:type="string">Training\ComputerGame\Model\ResourceModel\ComputerGame</argument>
    </arguments>
</virtualType>
<type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory">
    <arguments>
        <argument name="collections" xsi:type="array">
            <item name="game_record_grid_list_data_source" xsi:type="string">Training\ComputerGame\Model\ResourceModel\ComputerGame\Grid\Collection</item>
        </argument>
    </arguments>
</type>

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top