4

A while back I found a question on stackoverflow about allowing multiple products via a widget. I thought to myself that it would be a great option and surely could not be that difficult. Sadly I was wrong :( I have managed to get the mass action checkboxes and buttons to display on a widget but the JavaScript that goes with it is either not included or not working.

The grid is displayed include mass action options but when I try to use these items I get the following JavaScript error.

Uncaught ReferenceError: options_fieldset1adc562cf047406a634a7c10ae4f7db2_product_idsa765921c1aaf6166ee36c2e83468e0bf_massactionJsObject is not defined

So here is what I have done so far.

Created a app\etc\modules\Manners_Widgets.xml

<?xml version="1.0"?>
<config>
    <modules>
        <Manners_Widgets>
            <active>true</active>
            <codePool>community</codePool>
            <depends>
                <Mage_Adminhtml />
                <Mage_Widget />
            </depends>
        </Manners_Widgets>
    </modules>
</config>

Created a app\code\community\Manners\Widgets\etc\config.xml

<?xml version="1.0"?>
<config>
    <modules>
        <Manners_Widgets>
            <version>1.0.0</version>
        </Manners_Widgets>
    </modules>

    <global>
        <blocks>
            <manners_widgets>
                <class>Manners_Widgets_Block</class>
            </manners_widgets>
            <adminhtml>
                <rewrite>
                    <catalog_product_widget_chooser>Manners_Widgets_Block_Catalog_Product_Widget_Chooser</catalog_product_widget_chooser>
                </rewrite>
            </adminhtml>
        </blocks>

        <helpers>
            <manners_widgets>
                <class>Manners_Widgets_Helper</class>
            </manners_widgets>
        </helpers>
    </global>
</config>

Created a app\code\community\Manners\Widgets\etc\widget.xml

<?xml version="1.0"?>
<widgets>
    <manners_widgets_products type="manners_widgets/products" translate="name description" module="manners_widgets">
        <name>Multiple Products Widget</name>
        <description>Widget to display multiple products on one page</description>
        <parameters>
            <product_ids translate="label">
                <visible>1</visible>
                <required>1</required>
                <label>Product</label>
                <type>label</type>
                <helper_block>
                    <type>manners_widgets/catalog_product_widget_chooser</type>
                    <data>
                        <button translate="open remove">
                            <open>Select Products...</open>
                        </button>
                    </data>
                </helper_block>
            </product_ids>
        </parameters>
    </manners_widgets_products>
</widgets>

Finally I created my block Manners_Widgets_Block_Catalog_Product_Widget_Chooser

<?php
class Manners_Widgets_Block_Catalog_Product_Widget_Chooser extends Mage_Adminhtml_Block_Catalog_Product_Widget_Chooser {
    /**
     *
     * @return Mage_Adminhtml_Block_Widget_Grid|void
     */
    protected function _prepareColumns() {
        $this->addColumn('entity_id', array(
            'header'    => Mage::helper('catalog')->__('ID'),
            'sortable'  => true,
            'width'     => '60px',
            'index'     => 'entity_id'
        ));
        $this->addColumn('chooser_sku', array(
            'header'    => Mage::helper('catalog')->__('SKU'),
            'name'      => 'chooser_sku',
            'width'     => '80px',
            'index'     => 'sku'
        ));
        $this->addColumn('chooser_name', array(
            'header'    => Mage::helper('catalog')->__('Product Name'),
            'name'      => 'chooser_name',
            'index'     => 'name'
        ));
    }

    /**
     * Prepare the massaction
     *  - Block,
     *  - Item
     *
     * @return $this|Mage_Adminhtml_Block_Widget_Grid
     */
    protected function _prepareMassaction() {
        $this->setMassactionIdField('entity_id');
        $this->setMassactionIdFilter('entity_id');
        $this->getMassactionBlock()->setFormFieldName('product');

        $this->getMassactionBlock()->addItem('delete', array(
            'label'=> Mage::helper('catalog')->__('Add Products'),
            'url'  => $this->getUrl('*/*/addProducts')
        ));

        Mage::dispatchEvent('manners_widgets_catalog_product_grid_prepare_massaction', array('block' => $this));
        return $this;
    }

    /**
     * Checkbox Check JS Callback
     *
     * @return string
     */
    public function getCheckboxCheckCallback()
    {
        return "function (grid, element) {
            $(grid.containerId).fire('product:changed', {element: element});
        }";
    }

    /**
     * Grid Row JS Callback
     *
     * @return string
     */
    public function getRowClickCallback()
    {
        $chooserJsObject = $this->getId();
            return '
                function (grid, event) {
                    var trElement = Event.findElement(event, "tr");
                    var productId = trElement.down("td").innerHTML;
                    var productName = trElement.down("td").next().next().innerHTML;
                    var optionLabel = productName;
                    var optionValue = "product/" + productId.replace(/^\s+|\s+$/g,"");
                    if (grid.categoryId) {
                        optionValue += "/" + grid.categoryId;
                    }
                    if (grid.categoryName) {
                        optionLabel = grid.categoryName + " / " + optionLabel;
                    }
                    '.$chooserJsObject.'.setElementValue(optionValue);
                    '.$chooserJsObject.'.setElementLabel(optionLabel);
                    '.$chooserJsObject.'.close();
                }
            ';
    }
}

Original stackoverflow question

https://stackoverflow.com/questions/13493630/how-to-allow-multiple-product-selection-in-magento-widget-configuration

GitHub Repo

https://github.com/dmanners/Manners_Widgets

4
+50

First, here is why you get that error.
The mass action block button has this onclick event.

$this->getJsObjectName() . ".apply()"

Digging deeper in the methods the code above translates into

{parent_block_id}_massactionJsObject.apply();

(For a widget chooser the parent block id is some random hash but that's not important). The idea is that the object above does not exist.
Now the (possible) solution. Change the mass action block only for your widget chooser. For this create a new class:

<?php 
class Manners_Widgets_Block_Catalog_Product_Massaction extends Mage_Adminhtml_Block_Widget_Grid_Massaction{
    public function getApplyButtonHtml()
    {
        return $this->getButtonHtml($this->__('Submit'), "alert('Doh!')");//add this your js function that should do the magic.
    }
}

Now tell your grid to use this new mass action block. For this add int the class Manners_Widgets_Block_Catalog_Product_Widget_Chooser this method:

protected function _construct(){
    parent::_construct();
    $this->setMassactionBlockName('manners_widgets/catalog_product_massaction');
}

Now when you click on the "submit" button you will get an alert and no errors.
Change the alert in the code above with your actions.

  • thanks for the answer to the js error now I have no excuse to finish this massaction task in widgets :) – David Manners Oct 4 '13 at 14:33
  • @DavidManners You're welcome....and sorry :) If you want I can think of an excuse. Does it have to be believable? – Marius Oct 4 '13 at 14:38
7

This is a scope problem. The massactionJsObject is declared with "var" in Mage_Adminhtml_Block_Widget_Grid_Massaction_Abstract

public function getJavaScript()
{
    return " var {$this->getJsObjectName()} = new varienGridMassaction('{$this->getHtmlId()}', "
            . "{$this->getGridJsObjectName()}, '{$this->getSelectedJson()}'"
            . ", '{$this->getFormFieldNameInternal()}', '{$this->getFormFieldName()}');"
            . "{$this->getJsObjectName()}.setItems({$this->getItemsJson()}); "
            . "{$this->getJsObjectName()}.setGridIds('{$this->getGridIdsJson()}');"
            . ($this->getUseAjax() ? "{$this->getJsObjectName()}.setUseAjax(true);" : '')
            . ($this->getUseSelectAll() ? "{$this->getJsObjectName()}.setUseSelectAll(true);" : '')
            . "{$this->getJsObjectName()}.errorText = '{$this->getErrorText()}';";
}

If you override this method and remove the "var" keyword from the declaration, the scope will be global and the object accessible from the widget popup.

So,basicly:

  • Override Mage_Adminhtml_Block_Widget_Grid_Massaction with your block
  • override the method getJavascript removing the "var"
  • In your Widget_Product_Chooser block, set the protected $_massactionBlockName with your massaction block

    $_massactionBlockName = 'mymodule/widget_product_massaction';

I struggled 2 days on this :/ Hope this helps

  • Awesome answer. Saved me a lot of time I believe. – Alexey Shchur Sep 30 '14 at 8:25
0

A new feature in Magento 1.4.1. is that any filtering done on the Sales > Orders page is now updated via an AJAX call when hitting submit. Unfortunately this has an unindented side-effect: after any ajax updates the mass-actions (Cancel, Hold, Print Invoices, Print Packingslips, etc) will not work. Instead you will be thrown back to the Dashboard (or whatever else your current users start page in the admin area is).

After an ajax update Magento doesn’t load the complete layout of the page. However in the layout it keeps a form key to authenticate the submission of the request. Since this is now missing it will “decline” the request from the mass-action and you are thrown back to the dashboard.

To fix this issue you can edit app/design/adminhtml/default/default/template/widget/grid/massactions.phtml and change

<?php echo $this->getBlockHtml('formkey')?>

to

<div><input name="form_key" type="hidden" value="<?php echo Mage::getSingleton('core/session')->getFormKey() ?>" /></div>

On a sidenote: after being thrown back to the dashboard and visiting Sales > Orders for a second time it will remember your previous selection. And since it now has done a full page load the mass-action will succeed.

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.