How to disable action column item for a single row?
Asked Answered
G

5

10

Consider this JSON sample :

[{id:1,editable:true},{id:2,editable:false}]

These records are about to be loaded in a store, then displayed inside a grid panel. This grid has an action column item for edition purposes. I'm looking for a way to disable the "edit" button only for the second row without performing computation after rendering. I'd like to use a built in feature which works like the renderer property rather than to loop through the store to update each row once the grid has been rendered.

Does ExtJS 4.1.1 provides this kind of feature?

Gold answered 21/3, 2013 at 10:6 Comment(0)
G
2

I had forgotten this question until Louis posted his answer. I finally decided to override ActionColumn to add the missing features. Here is the code :

Ext.grid.column.Action.override({
    defaultRenderer: function (v, meta) {
        var me = this,
            disabled, tooltip,
            prefix = Ext.baseCSSPrefix,
            scope = me.origScope || me,
            items = me.items,
            len = items.length,
            i = 0,
            item;
        v = Ext.isFunction(me.origRenderer) ? me.origRenderer.apply(scope, arguments) || '' : '';
        meta.tdCls += ' ' + Ext.baseCSSPrefix + 'action-col-cell';
        for (; i < len; i++) {
            item = items[i];
            disabled = item.disabled || (item.isDisabled ? item.isDisabled.apply(item.scope || scope, arguments) : false);
            tooltip = disabled ? null : (item.tooltip || (item.getTip ? item.getTip.apply(item.scope || scope, arguments) : null));
            if (!item.hasActionConfiguration) {
                item.stopSelection = me.stopSelection;
                item.disable = Ext.Function.bind(me.disableAction, me, [i], 0);
                item.enable = Ext.Function.bind(me.enableAction, me, [i], 0);
                item.hasActionConfiguration = true;
            }
            v += '<img alt="' + (item.altText || me.altText) + '" src="' + (item.icon || Ext.BLANK_IMAGE_URL) +
            '" class="' + prefix + 'action-col-icon ' + prefix + 'action-col-' + String(i) + ' ' + (disabled ? prefix + 'item-disabled' : ' ') +
            ' ' + (Ext.isFunction(item.getClass) ? item.getClass.apply(item.scope || scope, arguments) : (item.iconCls || me.iconCls || '')) + '"' +
            (tooltip ? ' data-qtip="' + tooltip + '"' : '') + ' />';
        }
        return v;
    }
});
Gold answered 13/6, 2013 at 16:3 Comment(2)
I did it the same wayWinthrop
Yeah i did it that way too.Brockway
T
30

You can use set the isDisabled config (at least from version 4.2.1):

{
    xtype:'actioncolumn',
    width:20,
    items: [
        {
            icon: 'app/images/edit.png',
            tooltip: 'Edit this row',
            handler: function(gridview, rowIndex, colIndex, item, e, record, row) {
                var grid=gridview.up('grid');
                // You need to listen to this event on your grid.
                grid.fireEvent('editRecord', grid, record);
            },
            isDisabled: function(view, rowIndex, colIndex, item, record) {
                // Returns true if 'editable' is false (, null, or undefined)
                return !record.get('editable');
            }
    ]
}

When isDisabled(..) returns true the icon is blurred and the handler is not triggered on mouse click.

Teddy answered 12/6, 2013 at 9:15 Comment(1)
good example, works great. My obly suggestion is that your field names if for display should match the config option. IE 'displayIsDisabled'Scholasticism
S
9

I'm just going to start off by saying this: I avoid using action column at all costs, it's completely unable to do any sort of rendering logic (like different images per row, and showing conditionally based on the row model). Instead define a regular column that renders an image and takes advantage of the click event in the column. Here is an example from my code:

{
    header:    "&nbsp;",
    dataIndex: "some_index",
    width:     26,
    renderer: function(value, metaData){
        metaData.style += "padding:0px;";
        if(value)
            return "&nbsp;<img src=\"extjs/4.0/sms/icons/fam/magnifier.png\"/>";
        return value;
    },
    listeners: {
        click: function(gridView, htmlSomething, rowIndex, columnIndex, theEvent){
            var store = myGrid.getStore();
            var record = store.getAt(rowIndex);
            if(record.get("some_index"))
                //do action
        }
    }
}
Slalom answered 21/3, 2013 at 13:48 Comment(8)
Hi Reimius. That's nice but a bit too complex since the built-in features are lost. (jsFiddle)Gold
What features are missing?Slalom
Sorry for not being clear. I meant that I'll have to write some extra piece of styles and logic which are already provided using action columns. For example, I think about the disableAction method, or the ability to easily append items side by side, in a single column, using a simple config array. Maybe my question is not detailled enough.Gold
My code example is as simple as it gets. Ext 4.1.1 does not provide the feature you want without custom code.Slalom
I used to do this, I have a column w/ a little file icon, which does not occupy all the space of the column. User complains that clicking on the cell and not in the file icon itself triggers the action though... Did you find a way to do this?Slipover
Yes, if you want that you need to look into the event passed into the click handler. That event has a currentTarget or something like that and you can see if that is the image.Slalom
That is incorrect, and over coded. You use css and the getClass to change the look and feel of specific rows. Alternatively you could make an afterrender listener in your grid.Scholasticism
Did you consider the version in use here? This answer was for Extjs 4.1.1. Also, if you are trying to be helpful, please cite documentation for css and getClass (as in where they should be used), as those are very generic things to say and used just about everywhere.Slalom
K
3

I found the following solution in the Sencha Forum: Additionally to the "isDisabled"-function already described here, you can use the following config to change (or hide) the icon to display depending on the record:

getClass: function(value,metadata,record){
    if (record.get('description')){  //read your condition from the record
        return 'icon-pencil-go';    // add a CSS-Class to display what icon you like
    } else {
        return '';        //add no CSS-Class
    }
}

My CSS-class is defined as:

.icon-pencil-go {
    background-image: url('../images/icons/famfamfam/pencil_go.png') !important;
}

As I am displaying Icons via CSS anyway, this is a fast way for me to change icons dynamically. Please note, that disabling the handler via "isDisabled" is still nessecary, because otherwise the handler would start if you click the action column even if the icon is not displayed.

Kalakalaazar answered 28/4, 2015 at 10:46 Comment(2)
I can't try your solution since I stopped working on the related project a long time ago :-| Anyway, thanks for your contribution, it may be helpful for some other people :-)Gold
this doesn't remove the tooltip, only for changing look and feel.Scholasticism
G
2

I had forgotten this question until Louis posted his answer. I finally decided to override ActionColumn to add the missing features. Here is the code :

Ext.grid.column.Action.override({
    defaultRenderer: function (v, meta) {
        var me = this,
            disabled, tooltip,
            prefix = Ext.baseCSSPrefix,
            scope = me.origScope || me,
            items = me.items,
            len = items.length,
            i = 0,
            item;
        v = Ext.isFunction(me.origRenderer) ? me.origRenderer.apply(scope, arguments) || '' : '';
        meta.tdCls += ' ' + Ext.baseCSSPrefix + 'action-col-cell';
        for (; i < len; i++) {
            item = items[i];
            disabled = item.disabled || (item.isDisabled ? item.isDisabled.apply(item.scope || scope, arguments) : false);
            tooltip = disabled ? null : (item.tooltip || (item.getTip ? item.getTip.apply(item.scope || scope, arguments) : null));
            if (!item.hasActionConfiguration) {
                item.stopSelection = me.stopSelection;
                item.disable = Ext.Function.bind(me.disableAction, me, [i], 0);
                item.enable = Ext.Function.bind(me.enableAction, me, [i], 0);
                item.hasActionConfiguration = true;
            }
            v += '<img alt="' + (item.altText || me.altText) + '" src="' + (item.icon || Ext.BLANK_IMAGE_URL) +
            '" class="' + prefix + 'action-col-icon ' + prefix + 'action-col-' + String(i) + ' ' + (disabled ? prefix + 'item-disabled' : ' ') +
            ' ' + (Ext.isFunction(item.getClass) ? item.getClass.apply(item.scope || scope, arguments) : (item.iconCls || me.iconCls || '')) + '"' +
            (tooltip ? ' data-qtip="' + tooltip + '"' : '') + ' />';
        }
        return v;
    }
});
Gold answered 13/6, 2013 at 16:3 Comment(2)
I did it the same wayWinthrop
Yeah i did it that way too.Brockway
I
1

Ive used the following in ExtJs 6.0.1 version and works well. Use 'getClass' config. A function which returns the CSS class to apply to the icon image.

                {
                  xtype: 'actioncolumn',
                  flex: 1,
                  text: 'Action'
                  items: [{
                      tooltip: 'Import',
                      getClass: function (value, meta, record) {
                         if(record.get('Name') == 'disable'){
                             return 'x-hidden'; // when u want to hide icon
                         }
                      }
                         return 'x-grid-icon' ; // show icon


                  }]
                }
Improvident answered 18/5, 2016 at 15:3 Comment(1)
ExtJS 6! Time flies :-) Unfortunately I'm not able to evaluate your post anymore, this is job for the new generation :-) Thanks for your contribution anyway!Gold

© 2022 - 2024 — McMap. All rights reserved.