Question

Scenario:
I have a custom CRUD module and I need to have a mass action in the admin grid that I can use to mass update the status for example.
The module uses the new xml grid system from Magento 2 (see as example app/code/Magento/Sales/view/adminhtml/layout/sales_order_grid_block.xml).

Issue:
I can add any mass action item that does not require an additional input.

            <block class="Magento\Backend\Block\Widget\Grid\Massaction" name="[module].[entity].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="delete" xsi:type="array">
                            <item name="label" xsi:type="string" translate="true">Delete</item>
                            <item name="url" xsi:type="string">[module_route]/[entity]/massDelete</item>
                            <item name="confirm" xsi:type="string" translate="true">Are you sure you want to delete the items?</item>
                        </item>
                    </argument>
                </arguments>
            </block>

I cannot add a mass action item that requires an additional select. In the example above, I need a select with 2 statuses enabled & disabled.

In Magento 1 this was possible via _prepareMassaction method in the grid block:

    $this->getMassactionBlock()->addItem(
        'status',
        array(
            'label'      => Mage::helper('[module]')->__('Change status'),
            'url'        => $this->getUrl('*/*/massStatus', array('_current'=>true)),
            'additional' => array( //this allows an additional select.
                'status' => array(
                    'name'   => 'status',
                    'type'   => 'select',
                    'class'  => 'required-entry',
                    'label'  => Mage::helper('[module]')->__('Status'),
                    'values' => array(
                        '1' => Mage::helper('[module]')->__('Enabled'),
                        '0' => Mage::helper('[module]')->__('Disabled'),
                    )
                )
            )
        )
    );

Magento 1 result:

mass action

Question:
How can I get the same result in Magento 2 (0.74.0-beta1) via xml grid definition?

Was it helpful?

Solution

As it stands I don't think it's possible (without modifiying the behaviour of the addItem method.) it looks to me like the XML ability is used in Magento\Backend\Block\Widget\Grid\Massaction\AbstractMassaction which Magento\Backend\Block\Widget\Grid\Massaction\Extended doesn't extend but only Extended has the ability to add multiple action blocks.

However only Massaction\Extended has the correct template and to below code in the addItem method which adds the additional block.

if ($this->_items[$itemId]->getAdditional()) {
        $this->_items[$itemId]->setAdditionalActionBlock($this->_items[$itemId]->getAdditional());
        $this->_items[$itemId]->unsAdditional();
    }

I managed to make it work but it required using a plugin and updating the template via XML, you can then use XML like below:

 <action method="setTemplate">
                            <argument name="template" xsi:type="string">Magento_Backend::widget/grid/massaction_extended.phtml</argument>
                        </action>

.

<item name="cancel_order" xsi:type="array">
                                <item name="label" xsi:type="string" translate="true">Cancel</item>
                                <item name="url" xsi:type="string">sales/order/massCancel</item>
                                <item name="additional" xsi:type="array">
                                    <item name="visibility" xsi:type="array">
                                        <item name="name" xsi:type="string">name</item>
                                        <item name="type" xsi:type="string">select</item>
                                        <item name="class" xsi:type="string">required-entry</item>
                                        <item name="label" xsi:type="string">status</item>
                                        <item name="values" xsi:type="array">
                                            <item name="1" xsi:type="string">Enabled</item>
                                            <item name="0" xsi:type="string">Disabled</item>
                                        </item>
                                    </item>
                                </item>
                            </item>

The Preference (rewrite) I created for \Magento\Backend\Block\Widget\Grid\Massaction

etc/module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
    <module name="TheExtensionLab_Massaction" setup_version="0.0.1">
        <sequence>
            <module name="Magento_Config"/>
        </sequence>
    </module>
</config>

etc/di.xml

    <?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
    <type name="Magento\Backend\Block\Widget\Grid\Massaction">
        <plugin name="theextensionlab-massaction-add-additional" type="TheExtensionLab\Massaction\Model\Widget\Grid\Massaction\Plugin"/>
    </type>
</config>

TheExtensionLab\Massaction\Model\Widget\Grid\Massaction\Plugin.php

<?php
    namespace TheExtensionLab\Massaction\Model\Widget\Grid\Massaction;

    class Plugin extends \Magento\Backend\Block\Widget\Grid\Massaction
    {

        public function aroundAddItem($subject,$proceed,$itemId,$item){

            $returnValue = $proceed($itemId,$item);

            $returnValue->_items[$itemId] = $returnValue->getLayout()->createBlock(
                'Magento\Backend\Block\Widget\Grid\Massaction\Item'
            )->setData(
                $item
            )->setMassaction(
                $returnValue
            )->setId(
                $itemId
            );

            if ($returnValue->_items[$itemId]->getAdditional()) {
                $returnValue->_items[$itemId]->setAdditionalActionBlock($returnValue->_items[$itemId]->getAdditional());
                $returnValue->_items[$itemId]->unsAdditional();
            }

            return $returnValue;
        }

    }

Note: I'm not sure about extending the Plugin with the Massaction class just to be able to update the private variables but I figure thats better that rewriting/using preferences to edit just the one function.

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