6

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?

4

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.

  • This seams to work. Just one comment. Instead of using the around plugin, I think an after plugin would be safer. The first line of your plugin is $proceed($itemId,$item) so everything in your code is executed after the original method. around plugins are dangerous. But those are just details. I dug deeper based on your suggestions and indeed there is not way (I didn't find one) to add complex mass actions without plugins or preferences. This needs to be changed. Thank you for everything. – Marius Mar 30 '15 at 6:46
  • Hi @marius, yeah I thought the same thing but was unable to get the params in the After Plugin method and without them this gets more complicated I think because we don't then have the additional data to hand. Might ask M2 to add those in. – James Anelay - TheExtensionLab Mar 30 '15 at 10:01
  • 1
    I see now. I tested with your approach and it was enough for me. I just thought it might work with after plugin, but didn't test. apparently I was wrong. Anyway. I will open a ticked on M2, because we should be able to add complex mass actions via xml directly. Thanks. – Marius Mar 30 '15 at 10:55

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.