How to allow multiple product selection in Magento widget configuration?

Aleksandar Janković picture Aleksandar Janković · Nov 21, 2012 · Viewed 8.5k times · Source

I am trying to implement embedded widget. Administrators will be able to configure this widget and embed it inside WYSIWYG editor. Two of the many configuration options are list of products that should show up on frontend and list of categories.

I want to allow this selection with "adminhtml/catalog_product_widget_chooser" and "adminhtml/catalog_category_widget_chooser". I tried to implement these widgets with sparse documentation available on the web but all I managed to accomplish is implementation for selecting one product or selecting one category. I need multiselect behavior.

As far as I can see no multiselection possibility is allowed by the current implementation. I checked code for both classes and grid.phtml template and it seams it is badly written and not extensible beyond current intention of use. For example this is how you would suppose to initialize helper block for a widget parameter to allow multiple select:

<helper_block>
    <type>adminhtml/catalog_product_widget_chooser</type>
        <data>
            <button translate="open">
                <open>Select Products...</open>
            </button>
            <use_massaction>1</use_massaction>
        </data>
</helper_block>

But product chooser is hard coded for use without mass actions with this part of the code:

public function prepareElementHtml(Varien_Data_Form_Element_Abstract $element)
{
    $uniqId = Mage::helper('core')->uniqHash($element->getId());
    $sourceUrl = $this->getUrl('*/catalog_product_widget/chooser', array(
        'uniq_id' => $uniqId,
        'use_massaction' => false,
    ));
    ...

And grid.phtml template that is supposed to have some kind of button to confirm multiple selection is just showing "Search" and "Reset filter" buttons. And there is no handling of adding another button. For example here is the default code responsible for printing button html:

public function getMainButtonsHtml()
{
    $html = '';
    if($this->getFilterVisibility()){
        $html.= $this->getResetFilterButtonHtml();
        $html.= $this->getSearchButtonHtml();
    }
    return $html;
}

Only these two buttons are going to be printed by default.

So I started my own implementation based on two implementations mentioned above and it is getting ugly and could end up as an unmaintainable mess of copy-pasta. And I work by principle that if things start to look ugly then I am doing something wrong.

So is there a straightforward way to implement multiple product and multiple category selection on widget configuration screen by using grid widget?

Answer

kellen picture kellen · Oct 10, 2013

I've found a quick way to get category multiselects on widget parameters using a source model based on adminhtml/system_config_source_category. I've removed the root-level filter and added indentation for subcategories.

widget.xml:

<widgets>
    <my_widget type="mymodule/block" translate="name" module="mymodule">
        <name>Widget with Multiselect Categories</name>
        <parameters>
            <category_ids translate="label description">
                <visible>1</visible>
                <required>1</required>
                <label>Categories</label>
                <type>multiselect</type>
                <source_model>mymodule/system_config_source_category</source_model>
            </category_ids>
        </parameters>
    </my_widget>
</widgets>

The source model:

class Mynamespace_Mymodule_Model_System_Config_Source_Category
{
    public function toOptionArray()
    {
        $collection = Mage::getResourceModel('catalog/category_collection');

        $collection->addAttributeToSelect('name')
            ->addFieldToFilter('path', array('neq' => '1'))
            ->load();

        $options = array();

        foreach ($collection as $category) {
            $depth = count(explode('/', $category->getPath())) - 2;
            $indent = str_repeat('-', max($depth * 2, 0));
            $options[] = array(
               'label' => $indent . $category->getName(),
               'value' => $category->getId()
            );
        }

        return $options;
    }
}

The result:

Multiselect widget parameter

Source: http://www.magentocommerce.com/knowledge-base/entry/tutorial-creating-a-magento-widget-part-2