Question

I want to cancel default behavior on grid row click - checking massaction checkboxes. The another default action - is redirecting to an editing page, and I've disabled it in this way - add this method to my grid -

public function getRowUrl($row)
{
    return '';
}

I've also tried to use openGridRow() function, but it didn't work (I've placed it in my own js file). But I need to disable checkbox checking too. Does anybody know, how to do it? If it's possible to do with openGridRow(), where I need to place it?

Was it helpful?

Solution 2

Thanks to previous answer, I've finally find a solution - by adding this method

getRowClickCallback

to my grid class (that overrides a core grid Mage_Adminhtml_Block_Catalog_Product_Grid), that returns some fake JS function, like this

public function getRowClickCallback()
{
    return 'fakeJsFunction';
}

OTHER TIPS

With openGridRow you were already close to the solution. This is the default JS callback, but you can change it with the row_click_callback property of the grid widget. For no action at all, use:

$this->setRowClickCallback(null);

The default value is set in Mage_Adminhtml_Block_Widget_Grid::__construct(), so you can override the constructor and add this line after parent::__construct()

I've recently had a similar need--to alter the default behavior of a click in a row on a grid. I added a custom grid column renderer using a <textarea> field. Every time I clicked inside the textarea to type in some text, the row's "enabled"/"massaction" checkbox would toggle, and that was frustrating from a user perspective.

When any element is clicked in a grid row, varienGrid's rowClickCallback is called. However, there's more to it than that. When Magento's grid.js is loaded, it has more than just a varienGrid object. It also has a serializerController object. When this object is instantiated (after varienGrid), it overwrites a few of varienGrid's event handlers, including the rowClickCallback handler, but not before saving references to the "old" handlers in it's oldCallback array. So when varienGrid's rowMouseClick calls this.rowClickCallback(this, event), it's actually firing serializerController's rowClick method. Just before that method finishes, it calls the previous handler for the same event, which it stored in it's oldCallback array. In this way, both varienGrid.rowClickCallback and serializerController.rowClick are fired when any element is clicked in a grid row.

So, there's at least two methods that you'll need to consider. If you want to add behavior to a grid row click, you can either override the openGridRow function with your own, or you can write an entirely new function, and set it's name in your grid block's __constructor method using $this->setRowClickCallback('function_name') as @fschmengler mentioned. Note that calling $this->setRowClickCallback(null); will only disable varienGrid's rowClickCallback method, but serializerController's rowClick will still fire.

For my issue, I wanted clicks on textareas to not toggle the row's "enabled"/"massaction" checkbox. I therefore had to change the behavior of serializerController.rowClick by loading my own JS file as part of my module's adminhtml layout, and including this bit:

if(typeof tmpSerializerController == 'undefined') {
   var tmpSerializerController = {};
}
tmpSerializerController = Class.create(serializerController, {
    rowClick : function(grid, event) {
        var trElement = Event.findElement(event, 'tr');
        var isControl = ['a', 'input', 'select', 'option', 'textarea', 'img', 'label'].indexOf(Event.element(event).tagName.toLowerCase()) != -1;
        if(trElement){
            var checkbox = Element.select(trElement, 'input');
            if (checkbox[0] && !checkbox[0].disabled) {
                var checked = isControl ? checkbox[0].checked : !checkbox[0].checked;
                this.grid.setCheckboxChecked(checkbox[0], checked);
            }
        }
        this.getOldCallback('row_click')(grid, event);
    },
    rowInit : function(grid, row) {
        if(this.multidimensionalMode){
            var checkbox = $(row).select('.checkbox')[0];
            var selectors = this.inputsToManage.map(function (name) { return ['input[name="' + name + '"]', 'input[type="file"]', 'select[name="' + name + '"]', 'textarea[name="' + name + '"]']; });
            var inputs = $(row).select.apply($(row), selectors.flatten());
            if(checkbox && inputs.length > 0) {
                checkbox.inputElements = inputs;
                for(var i = 0; i < inputs.length; i++) {
                    inputs[i].checkboxElement = checkbox;
                    if(this.gridData.get(checkbox.value) && this.gridData.get(checkbox.value)[inputs[i].name]) {
                        inputs[i].value = this.gridData.get(checkbox.value)[inputs[i].name];
                    }
                    inputs[i].disabled = !checkbox.checked;
                    inputs[i].tabIndex = this.tabIndex++;
                    Event.observe(inputs[i],'keyup', this.inputChange.bind(this));
                    Event.observe(inputs[i],'change', this.inputChange.bind(this));
                }
            }
        }
        this.getOldCallback('init_row')(grid, row);
    },
});
serializerController = tmpSerializerController;

I also added links, select menus, images and labels to cancel the row's toggling, as clicking on those don't really suggest an intention to toggle a row to me. EDIT: I added the rowInit method above to include the file inputs and textarea fields in the list of row inputs. This will allow them to be automatically disabled when the row is disabled, and re-enabled when the row is enabled.

To complete this answer, I should also mention varienGridMassaction's onGridRowClick. To be honest, I'm not quite sure how or when this is used. The varienGridMassaction instance does store and replace varienGrid's existing rowClickCallback function, but it's own onRowClickCallback method doesn't call the stored method. Perhaps someone can enlighten us on that point. Nonetheless, I updated it's logic to be consistent with the previous change made.

if (typeof tmpVarienGridMassaction == 'undefied') {
    var tmpVarienGridMassaction = {};
}
tmpVarienGridMassaction = Class.create(varienGridMassaction, {
    onGridRowClick: function(grid, evt) {
        var tdElement = Event.findElement(evt, 'td');
        var trElement = Event.findElement(evt, 'tr');

        if(!$(tdElement).down('input')) {
            if($(tdElement).down('a') || $(tdElement).down('select')) {
                return;
            }
            if (trElement.title) {
                setLocation(trElement.title);
            }
            else{
                var checkbox = Element.select(trElement, 'input');
                var isControl = ['a', 'input', 'select', 'option', 'textarea', 'img', 'label'].indexOf(Event.element(event).tagName.toLowerCase()) != -1;
                var checked = isControl ? checkbox[0].checked : ! checkbox[0].checked;

                if (checked) {
                    this.checkedString = varienStringArray.add(checkbox[0].value, this.checkedString);
                } else {
                    this.checkedString = varienStringArray.remove(checkbox[0].value, this.checkedString);
                }
                this.grid.setCheckboxChecked(checkbox[0], checked);
                this.updateCount();
            }
            return;
        }

        if(Event.element(evt).isMassactionCheckbox) {
           this.setCheckbox(Event.element(evt));
        } else if (checkbox = this.findCheckbox(evt)) {
           checkbox.checked = !checkbox.checked;
           this.setCheckbox(checkbox);
        }
    }
});
varienGridMassaction = tmpVarienGridMassaction;
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top