Magento – Mass action in custom grid block Magento 2 not showing

adminhtmlgridmagento-2.1magento2massaction

I've created a product grid block following this tutorial, right now i want to add new massAction item but the mass action field won't show up in the toolbar grid, here's the xml file:

<?xml version="1.0" ?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <update handle="styles"/>
    <body>
        <referenceContainer name="content">
            <block class="Lime\Lazada\Block\Adminhtml\Listingproduct\Products" name="lazada_listingproduct_products"/>
             <action method="addTab">
                    <argument name="name" xsi:type="string">products_section</argument>
                    <argument name="block" xsi:type="array">
                            <item name="label" xsi:type="string">Select Products</item>
                            <item name="title" xsi:type="string">Select Products</item>
                            <item name="url" xsi:type="helper" helper="Lime\Lazada\Helper\Data::getProductsGridUrl2"></item>
                            <item name="class" xsi:type="string">ajax</item>
                    </argument>
            </action>
            <listingToolbar name="listing_top">
                 <massaction name="listing_massaction">
                         <action name="export">
                                 <argument name="data" xsi:type="array">
                                         <item name="config" xsi:type="array">
                                                 <item name="type" xsi:type="string">export</item>
                                                 <item name="label" xsi:type="string" translate="true">Export to CSV</item>
                                                 <item name="url" xsi:type="string">productExport/productexport/exportCsv</item>
                                         </item>
                                 </argument>
                         </action>
                 </massaction>
            </listingToolbar> 
        </referenceContainer>
    </body>
</page>

the listingtoolbar should load the mass action but it never shows up, here's the block class code:

class Products extends \Magento\Backend\Block\Widget\Grid\Extended
{
    /**
     * @var \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory
     */
    protected $productCollectionFactory;

    /**
     * Listing factory
     *
     * @var ListingFactory
     */
    protected $listingFactory;

    /**
     * @var  \Magento\Framework\Registry
     */
    protected $registry;

    protected $_objectManager = null;

    /**
     *
     * @param \Magento\Backend\Block\Template\Context $context
     * @param \Magento\Backend\Helper\Data $backendHelper
     * @param \Magento\Framework\Registry $registry
     * @param ListingFactory $attachmentFactory
     * @param \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory
     * @param array $data
     */
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,
        \Magento\Backend\Helper\Data $backendHelper,
        \Magento\Framework\Registry $registry,
        \Magento\Framework\ObjectManagerInterface $objectManager,
        ListingFactory $listingFactory,
        \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory,
        array $data = []
    ) {
        $this->listingFactory = $listingFactory;
        $this->productCollectionFactory = $productCollectionFactory;
        $this->_objectManager = $objectManager;
        $this->registry = $registry;
        parent::__construct($context, $backendHelper, $data);
    }

    /**
     * _construct
     * @return void
     */
    protected function _construct()
    {
        parent::_construct();
        $this->setId('productsGrid');
        $this->setDefaultSort('entity_id');
        $this->setDefaultDir('DESC');
        $this->setSaveParametersInSession(true);
        $this->setUseAjax(true);
        if ($this->getRequest()->getParam('listing_id')) {
            $this->setDefaultFilter(array('in_product' => 1));
        }
    }

    /**
     * add Column Filter To Collection
     */
    protected function _addColumnFilterToCollection($column)
    {
        if ($column->getId() == 'in_product') {
            $productIds = $this->_getSelectedProducts();

            if (empty($productIds)) {
                $productIds = 0;
            }
            if ($column->getFilter()->getValue()) {
                $this->getCollection()->addFieldToFilter('entity_id', array('in' => $productIds));
            } else {
                if ($productIds) {
                    $this->getCollection()->addFieldToFilter('entity_id', array('nin' => $productIds));
                }
            }
        } else {
            parent::_addColumnFilterToCollection($column);
        }

        return $this;
    }

    /**
     * prepare collection
     */
    protected function _prepareCollection()
    {
        $collection = $this->productCollectionFactory->create();
        $collection->addAttributeToSelect('name');
        $collection->addAttributeToSelect('sku');
        $collection->addAttributeToSelect('price');
        $this->setCollection($collection);
        return parent::_prepareCollection();
    }

    /**
     * @return $this
     */
    protected function _prepareColumns()
    {
        /* @var $model \Lime\Lazada\Model\Slide */
        $model = $this->_objectManager->get('\Lime\Lazada\Model\Listing');

        $this->addColumn(
            'in_product',
            [
                'header_css_class' => 'a-center',
                'type' => 'checkbox',
                'name' => 'in_product',
                'align' => 'center',
                'index' => 'entity_id',
                'values' => $this->_getSelectedProducts(),
            ]
        );

        $this->addColumn(
            'entity_id',
            [
                'header' => __('Product ID'),
                'type' => 'number',
                'index' => 'entity_id',
                'header_css_class' => 'col-id',
                'column_css_class' => 'col-id',
            ]
        );
        $this->addColumn(
            'name',
            [
                'header' => __('Name'),
                'index' => 'name',
                'class' => 'xxx',
                'width' => '50px',
            ]
        );
        $this->addColumn(
            'sku',
            [
                'header' => __('Sku'),
                'index' => 'sku',
                'class' => 'xxx',
                'width' => '50px',
            ]
        );
        $this->addColumn(
            'price',
            [
                'header' => __('Price'),
                'type' => 'currency',
                'index' => 'price',
                'width' => '50px',
            ]
        );

        return parent::_prepareColumns();
    }

    /**
     * @return string
     */
    public function getGridUrl()
    {
        return $this->getUrl('*/*/productsgrid', ['_current' => true]);
    }

    /**
     * @param  object $row
     * @return string
     */
    public function getRowUrl($row)
    {
        return '';
    }

    protected function _getSelectedProducts()
    {
        $listing = $this->getListing();
        return $listing->getProducts($listing);
    }

    /**
     * Retrieve selected products
     *
     * @return array
     */
    public function getSelectedProducts()
    {
        $listing = $this->getListing();
        $selected = $listing->getProducts($listing);

        if (!is_array($selected)) {
            $selected = [];
        }
        return $selected;
    }

    protected function getListing()
    {
        $listingId = $this->getRequest()->getParam('listing_id');
        $listing   = $this->listingFactory->create();
        if ($listingId) {
            $listing->load($listingId);
        }
        return $listing;
    }

    /**
     * {@inheritdoc}
     */
    public function canShowTab()
    {
        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function isHidden()
    {
        return true;
    }
}

Best Answer

It's because your layout file is a mix between standard grid system and the UI Component system.

You need to replace the following code:

        <listingToolbar name="listing_top">
             <massaction name="listing_massaction">
                     <action name="export">
                             <argument name="data" xsi:type="array">
                                     <item name="config" xsi:type="array">
                                             <item name="type" xsi:type="string">export</item>
                                             <item name="label" xsi:type="string" translate="true">Export to CSV</item>
                                             <item name="url" xsi:type="string">productExport/productexport/exportCsv</item>
                                     </item>
                             </argument>
                     </action>
             </massaction>
        </listingToolbar>

With:

<referenceBlock name="lazada_listingproduct_products">
            <block class="Magento\Backend\Block\Widget\Grid\Massaction" name="adminhtml.indexer.grid.grid.massaction" as="grid.massaction">
                <arguments>
                    <argument name="massaction_id_field" xsi:type="string">entity_id</argument>
                    <argument name="form_field_name" xsi:type="string">entity_ids</argument>
                    <argument name="use_select_all" xsi:type="string">1</argument>
                    <argument name="options" xsi:type="array">
                        <item name="export" xsi:type="array">
                            <item name="label" xsi:type="string" translate="true">Export to CSV</item>
                            <item name="url" xsi:type="string">productExport/productexport/exportCsv</item>
                        </item>
                    </argument>
                </arguments>
            </block>
</referenceBlock>

Alternatively, you can add the massaction in pure PHP by adding the following method to your grid block file:

protected function _prepareMassaction()
{
    $this->setMassactionIdField('entity_id');
    $this->getMassactionBlock()->setFormFieldName('walltwotime');

    $this->getMassactionBlock()->addItem(
        'export',
        [
            'label' => __('Export To CSV'),
            'url' => $this->getUrl('productExport/productexport/exportcsv')
        ]
    );

    return $this;
}