Question

The feature I'm implementing is not a really required, so I won't include an extra library of threads just for that. But if someone knows a workaround I will appreciate it.

So I have a grid of 256 rows and 3 columns; one those columns is a checkboxColumn (similar to the one used here). But that checkboxColumn plugin has being modified to show a checkbox in the header in order to allow a kind of Check-All and Check-None features.

Because there are so many rows, the check-all process is taking to long. So I decided to put a "Spinning wheel" (waiting gif-animation). And now the problem is that the animation doesn't work. So I put a defer call to allow the rendering of the animated icon, but it seems like that defer is not enough for the animation to run. Although this defer at least allows showing the first frame of the waiting gif, instead of showing the checked-state for about a minute until the unchecked-state is show when everything is done.

Here is the expensive method:

internalSetAllColumn: function(column, newValue) {
    column.masterValue = newValue;
    column.header = '<div class="x-grid3-check-col-td loading-indicator">&#160;</div>'; // loading icon
    this.grid.getView().updateHeaders();
    (function() {
        this.grid.getStore().each(function(rec) {
            if (this.isCellEditable(rec)) {
                rec.set(this.dataIndex, newValue);
            }
        }, this);
        column.renderHeaderCheck();
        this.grid.getView().updateHeaders();
    }).defer(50, this);
}

And you can see a working example at the following code snippet:

/*global Ext */

Ext.grid.CheckColumn = function(config){
    Ext.apply(this, config);
    if(!this.id){
        this.id = Ext.id();
    }
    this.headerText = this.headerText || this.header || '&#160;';
    this.renderer = this.renderer.createDelegate(this);
};
Ext.grid.CheckColumn.prototype = {
    init: function(grid) {
        this.grid = grid;
        var column = this.grid.getColumnModel().getColumnById(this.id);
        column.masterValue = false;
        if (this.headerCheck) {
            column.renderHeaderCheck();
        }
        this.grid.on('headerclick', this.onHeaderClick, this);
        this.grid.on('render', function() {
            var view = this.grid.getView();
            view.mainBody.on('mousedown', this.onMouseDown, this);
            view.updateHeaders();
        }, this);
    }
    , dataIndex: ''
    , masterValue: false
    , width: 90
    , fixed: true
    , headerCheck: false
    , enableHeaderControl: true
    , onMouseDown: function(e, t) {
        if (!this.readonly) {
            if (Ext.fly(t).hasClass('x-grid3-cc-' + this.id)) {
                e.stopEvent();
                var editEvent = {};
                editEvent.row = this.grid.getView().findRowIndex(t);
                editEvent.column = this.grid.getColumnModel().findColumnIndex(this.dataIndex);
                editEvent.grid = this.grid;
                editEvent.field = this.dataIndex;
                editEvent.record = this.grid.store.getAt(editEvent.row);
                editEvent.originalValue = editEvent.record.data[this.dataIndex];
                editEvent.value = !editEvent.originalValue;
                editEvent.record.set(editEvent.field, editEvent.value);
                editEvent.grid.fireEvent('afteredit', editEvent);
            }
        }
    },

    getCheckedCls: function(v) {
        return v === -1 ? 'x-grid3-check-col-gray' : (v ? 'x-grid3-check-col-on' : 'x-grid3-check-col');
    },

    renderHeaderCheck: function() {
        this.header = '<div class="' + this.getCheckedCls(this.masterValue) + '">' + this.headerText + '</div>';
    },

    onHeaderClick: function(grid, columnIndex, event) {
        var colModel = grid.getColumnModel();
        var cIndex = colModel.getIndexById(this.id);
        if (cIndex == columnIndex && this.enableHeaderControl !== false && this.headerCheck) {
            var column = colModel.getColumnById(this.id);
            var newValue = !column.masterValue;
            this.internalSetAllColumn(column, newValue);
            colModel.fireEvent("headerchange", colModel, columnIndex, column.header);
            this.grid.getView().updateHeaders();
        }
    },

    renderer: function(v, p, record, rowIndex, colIndex, store) {
        p.css += ' x-grid3-check-col-td';
        return '<div class="' + this.getCheckedCls(v) + ' x-grid3-cc-' + this.id + '"> </div>';
    },

    internalSetAllColumn: function(column, newValue) {
        column.masterValue = newValue;
        column.header = '<div class="x-grid3-check-col-td loading-indicator">&#160;</div>'; // loading icon
        this.grid.getView().updateHeaders();
        (function() {
            this.grid.getStore().each(function(rec) {
                rec.set(this.dataIndex, newValue);
            }, this);
            column.renderHeaderCheck();
            this.grid.getView().updateHeaders();
        }).defer(50, this);
    },

    setAllColumn: function(columnIndex, newValue) {
        var colModel = this.grid.getColumnModel();
        var colId = colModel.getColumnId(columnIndex);
        var column = colModel.getColumnById(colId);
        this.internalSetAllColumn(column, newValue);
        this.grid.getView().updateHeaders();
    }
};

// -----------------------------------------
// End of plugin - Beginning of example code
// -----------------------------------------

        var chkColCountry = new Ext.grid.CheckColumn({ dataIndex: 'State.After', width: 50, headerCheck: true });

        var dsCountries = new Ext.data.ArrayStore({
            fields: ['Id', 'Name']
            , data: [["US","United States"],["CA","Canada"],["AF","Afghanistan"],["AL","Albania"],["DZ","Algeria"],["DS","American Samoa"],["AD","Andorra"],["AO","Angola"],["AI","Anguilla"],["AQ","Antarctica"],["AG","Antigua and/or Barbuda"],["AR","Argentina"],["AM","Armenia"],["AW","Aruba"],["AU","Australia"],["AT","Austria"],["AZ","Azerbaijan"],["BS","Bahamas"],["BH","Bahrain"],["BD","Bangladesh"],["BB","Barbados"],["BY","Belarus"],["BE","Belgium"],["BZ","Belize"],["BJ","Benin"],["BM","Bermuda"],["BT","Bhutan"],["BO","Bolivia"],["BA","Bosnia and Herzegovina"],["BW","Botswana"],["BV","Bouvet Island"],["BR","Brazil"],["IO","British lndian Ocean Territory"],["BN","Brunei Darussalam"],["BG","Bulgaria"],["BF","Burkina Faso"],["BI","Burundi"],["KH","Cambodia"],["CM","Cameroon"],["CV","Cape Verde"],["KY","Cayman Islands"],["CF","Central African Republic"],["TD","Chad"],["CL","Chile"],["CN","China"],["CX","Christmas Island"],["CC","Cocos (Keeling) Islands"],["CO","Colombia"],["KM","Comoros"],["CG","Congo"],["CK","Cook Islands"],["CR","Costa Rica"],["HR","Croatia (Hrvatska)"],["CU","Cuba"],["CY","Cyprus"],["CZ","Czech Republic"],["DK","Denmark"],["DJ","Djibouti"],["DM","Dominica"],["DO","Dominican Republic"],["TP","East Timor"],["EC","Ecudaor"],["EG","Egypt"],["SV","El Salvador"],["GQ","Equatorial Guinea"],["ER","Eritrea"],["EE","Estonia"],["ET","Ethiopia"],["FK","Falkland Islands (Malvinas)"],["FO","Faroe Islands"],["FJ","Fiji"],["FI","Finland"],["FR","France"],["FX","France, Metropolitan"],["GF","French Guiana"],["PF","French Polynesia"],["TF","French Southern Territories"],["GA","Gabon"],["GM","Gambia"],["GE","Georgia"],["DE","Germany"],["GH","Ghana"],["GI","Gibraltar"],["GR","Greece"],["GL","Greenland"],["GD","Grenada"],["GP","Guadeloupe"],["GU","Guam"],["GT","Guatemala"],["GN","Guinea"],["GW","Guinea-Bissau"],["GY","Guyana"],["HT","Haiti"],["HM","Heard and Mc Donald Islands"],["HN","Honduras"],["HK","Hong Kong"],["HU","Hungary"],["IS","Iceland"],["IN","India"],["ID","Indonesia"],["IR","Iran (Islamic Republic of)"],["IQ","Iraq"],["IE","Ireland"],["IL","Israel"],["IT","Italy"],["CI","Ivory Coast"],["JM","Jamaica"],["JP","Japan"],["JO","Jordan"],["KZ","Kazakhstan"],["KE","Kenya"],["KI","Kiribati"],["KP","Korea, Democratic People's Republic of"],["KR","Korea, Republic of"],["KW","Kuwait"],["KG","Kyrgyzstan"],["LA","Lao People's Democratic Republic"],["LV","Latvia"],["LB","Lebanon"],["LS","Lesotho"],["LR","Liberia"],["LY","Libyan Arab Jamahiriya"],["LI","Liechtenstein"],["LT","Lithuania"],["LU","Luxembourg"],["MO","Macau"],["MK","Macedonia"],["MG","Madagascar"],["MW","Malawi"],["MY","Malaysia"],["MV","Maldives"],["ML","Mali"],["MT","Malta"],["MH","Marshall Islands"],["MQ","Martinique"],["MR","Mauritania"],["MU","Mauritius"],["TY","Mayotte"],["MX","Mexico"],["FM","Micronesia, Federated States of"],["MD","Moldova, Republic of"],["MC","Monaco"],["MN","Mongolia"],["MS","Montserrat"],["MA","Morocco"],["MZ","Mozambique"],["MM","Myanmar"],["NA","Namibia"],["NR","Nauru"],["NP","Nepal"],["NL","Netherlands"],["AN","Netherlands Antilles"],["NC","New Caledonia"],["NZ","New Zealand"],["NI","Nicaragua"],["NE","Niger"],["NG","Nigeria"],["NU","Niue"],["NF","Norfork Island"],["MP","Northern Mariana Islands"],["NO","Norway"],["OM","Oman"],["PK","Pakistan"],["PW","Palau"],["PA","Panama"],["PG","Papua New Guinea"],["PY","Paraguay"],["PE","Peru"],["PH","Philippines"],["PN","Pitcairn"],["PL","Poland"],["PT","Portugal"],["PR","Puerto Rico"],["QA","Qatar"],["RE","Reunion"],["RO","Romania"],["RU","Russian Federation"],["RW","Rwanda"],["KN","Saint Kitts and Nevis"],["LC","Saint Lucia"],["VC","Saint Vincent and the Grenadines"],["WS","Samoa"],["SM","San Marino"],["ST","Sao Tome and Principe"],["SA","Saudi Arabia"],["SN","Senegal"],["SC","Seychelles"],["SL","Sierra Leone"],["SG","Singapore"],["SK","Slovakia"],["SI","Slovenia"],["SB","Solomon Islands"],["SO","Somalia"],["ZA","South Africa"],["GS","South Georgia South Sandwich Islands"],["ES","Spain"],["LK","Sri Lanka"],["SH","St. Helena"],["PM","St. Pierre and Miquelon"],["SD","Sudan"],["SR","Suriname"],["SJ","Svalbarn and Jan Mayen Islands"],["SZ","Swaziland"],["SE","Sweden"],["CH","Switzerland"],["SY","Syrian Arab Republic"],["TW","Taiwan"],["TJ","Tajikistan"],["TZ","Tanzania, United Republic of"],["TH","Thailand"],["TG","Togo"],["TK","Tokelau"],["TO","Tonga"],["TT","Trinidad and Tobago"],["TN","Tunisia"],["TR","Turkey"],["TM","Turkmenistan"],["TC","Turks and Caicos Islands"],["TV","Tuvalu"],["UG","Uganda"],["UA","Ukraine"],["AE","United Arab Emirates"],["GB","United Kingdom"],["UM","United States minor outlying islands"],["UY","Uruguay"],["UZ","Uzbekistan"],["VU","Vanuatu"],["VA","Vatican City State"],["VE","Venezuela"],["VN","Vietnam"],["VG","Virigan Islands (British)"],["VI","Virgin Islands (U.S.)"],["WF","Wallis and Futuna Islands"],["EH","Western Sahara"],["YE","Yemen"],["YU","Yugoslavia"],["ZR","Zaire"],["ZM","Zambia"],["ZW","Zimbabwe"]]
            , autoLoad: false
        });

        var cmCountry = new Ext.grid.ColumnModel([
            chkColCountry
            , { id: 'Id', header: 'Id', dataIndex: 'Id', width: 40 }
            , { id: 'Name', header: 'CountryName', dataIndex: 'Name', width: 460 }
            , { id: 'After', header: 'After', dataIndex: 'State.After', hidden: true }
        ]);

        var grdCountries = new Ext.grid.GridPanel({
            store: dsCountries
            , cm: cmCountry
            , plugins: chkColCountry
            , enableHdMenu: false
        });

        var win = new Ext.Window({
          layout: 'fit'
          , height: 190
          , width: 600
          , items: [grdCountries]
        });
        win.show();
<link href="//cdnjs.cloudflare.com/ajax/libs/extjs/3.4.1-1/resources/css/ext-all.css" rel="stylesheet"/>
<script src="//cdnjs.cloudflare.com/ajax/libs/extjs/3.4.1-1/adapter/ext/ext-base.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/extjs/3.4.1-1/ext-all.js"></script>

Click on the column checkbox (the one on the header) and see the gif that isn't spinning as expected.

Note: I have paging functionality in other places but I won't use it here as the 256 rows are always the same. So I rather lose the check all button than paging this.

Was it helpful?

Solution

The problem is not the use of .defer(), it's that you're doing it at the wrong level. The tight loop over the records is what's causing the freeze, and you aren't actually offloading those UI updates to another thread, you're simply delaying execution of the loop. When the loop kicks off after 50 milliseconds, it's still a tight loop that takes a while to execute.

This is a quick fix that, while not optimal, is probably closer to what you want:

    this.grid.getStore().each(function(rec) {
       rec.set.defer(1, rec, [this.dataIndex, newValue]);
    }, this);
    column.renderHeaderCheck();
    this.grid.getView().updateHeaders();

A couple of notes. If you are using defer to simply execute code on another thread (and not truly because you need a specific delay) just use 1 ms. No need to wait longer for no reason.

Secondly, beware using defer like this -- it may work for this case, but this is not a general best practice. When you start deferring stuff (especially in a loop like this), it can potentially cause issues if other code executes during the middle of your loop that might also affect your underlying store. Ideally, you'd be able to find a more suitable solution like deferring only the grid's UI update, but I suspect doing so might require an override or two (not sure off the top of my head). So if this solves it for you, great -- but don't say I didn't warn you if some other weird bug pops up later ;)

BTW, if you are scrolled down in the grid, there will still be a noticeable delay to the user since the loop still executes top to bottom. You could get fancy and update the visible records first before moving on to the rest of the data set -- depends on how much effort you want to put into it.

EDIT: OK, after putting a little more thought into this, all you need to do to avoid UI updates is tell the store not to fire its update events during the loop, then manually refresh the grid after all data updates are done. With this approach you shouldn't even need a spinner in the header, and you avoid all the potential issues with defer. Try this:

internalSetAllColumn: function(column, newValue) {
    var store = this.grid.getStore(),
        gridView = this.grid.getView();

    column.masterValue = newValue;

    store.suspendEvents();
    store.each(function(rec) {
        rec.set(this.dataIndex, newValue);
    }, this);
    store.resumeEvents();

    column.renderHeaderCheck();
    gridView.refresh();
}

OTHER TIPS

Instead of using defer, trying using Ext.TaskMgr which allows you to create a task and run it in a multithreaded manner.

Example of a task.

var task = {
    run: function(){
        Ext.fly('clock').update(new Date().format('g:i:s A'));
    },
    interval: 1000 //1 second
}
Ext.TaskMgr.start(task);

Too tricky probably, but it does show the animated spinning wheel, and seems to work just fine:

internalSetAllColumn: function(column, newValue) {
    column.masterValue = newValue;
    column.header = '<div class="x-grid3-check-col-td loading-indicator">&#160;</div>'; // loading icon
    this.grid.getView().updateHeaders();
    var store = this.grid.getStore();
    var count = store.getCount();
    var step = 5;
    var times = (count / step) >> 0;
    var task = {
        run: function() {
            var last = step * task.taskRunCount;
            var first = last - step;
            if (first <= count) {
                var recs = store.getRange(first, last);
                Ext.each(recs, function(rec) {
                    rec.set(this.dataIndex, newValue);
                }, this);
            }
            if (task.taskRunCount > times) {
                column.renderHeaderCheck();
                this.grid.getView().updateHeaders();
                return false;
            }
        },
        interval: 1,
        scope: this
    };
    Ext.TaskMgr.start(task);
}

/*global Ext */

Ext.grid.CheckColumn = function(config){
    Ext.apply(this, config);
    if(!this.id){
        this.id = Ext.id();
    }
    this.headerText = this.headerText || this.header || '&#160;';
    this.renderer = this.renderer.createDelegate(this);
};
Ext.grid.CheckColumn.prototype = {
    init: function(grid) {
        this.grid = grid;
        var column = this.grid.getColumnModel().getColumnById(this.id);
        column.masterValue = false;
        if (this.headerCheck) {
            column.renderHeaderCheck();
        }
        this.grid.on('headerclick', this.onHeaderClick, this);
        this.grid.on('render', function() {
            var view = this.grid.getView();
            view.mainBody.on('mousedown', this.onMouseDown, this);
            view.updateHeaders();
        }, this);
    }
    , dataIndex: ''
    , masterValue: false
    , width: 90
    , fixed: true
    , headerCheck: false
    , enableHeaderControl: true
    , onMouseDown: function(e, t) {
        if (!this.readonly) {
            if (Ext.fly(t).hasClass('x-grid3-cc-' + this.id)) {
                e.stopEvent();
                var editEvent = {};
                editEvent.row = this.grid.getView().findRowIndex(t);
                editEvent.column = this.grid.getColumnModel().findColumnIndex(this.dataIndex);
                editEvent.grid = this.grid;
                editEvent.field = this.dataIndex;
                editEvent.record = this.grid.store.getAt(editEvent.row);
                editEvent.originalValue = editEvent.record.data[this.dataIndex];
                editEvent.value = !editEvent.originalValue;
                editEvent.record.set(editEvent.field, editEvent.value);
                editEvent.grid.fireEvent('afteredit', editEvent);
            }
        }
    },

    getCheckedCls: function(v) {
        return v === -1 ? 'x-grid3-check-col-gray' : (v ? 'x-grid3-check-col-on' : 'x-grid3-check-col');
    },

    renderHeaderCheck: function() {
        this.header = '<div class="' + this.getCheckedCls(this.masterValue) + '">' + this.headerText + '</div>';
    },

    onHeaderClick: function(grid, columnIndex, event) {
        var colModel = grid.getColumnModel();
        var cIndex = colModel.getIndexById(this.id);
        if (cIndex == columnIndex && this.enableHeaderControl !== false && this.headerCheck) {
            var column = colModel.getColumnById(this.id);
            var newValue = !column.masterValue;
            this.internalSetAllColumn(column, newValue);
            colModel.fireEvent("headerchange", colModel, columnIndex, column.header);
            this.grid.getView().updateHeaders();
        }
    },

    renderer: function(v, p, record, rowIndex, colIndex, store) {
        p.css += ' x-grid3-check-col-td';
        return '<div class="' + this.getCheckedCls(v) + ' x-grid3-cc-' + this.id + '"> </div>';
    },

    internalSetAllColumn: function(column, newValue) {
        column.masterValue = newValue;
        column.header = '<div class="x-grid3-check-col-td loading-indicator">&#160;</div>'; // loading icon
        this.grid.getView().updateHeaders();
        var store = this.grid.getStore();
        var count = store.getCount();
        var step = 5;
        var times = (count / step) >> 0;
        var task = {
            run: function() {
                var last = step * task.taskRunCount;
                var first = last - step;
                if (first <= count) {
                    var recs = store.getRange(first, last);
                    Ext.each(recs, function(rec) {
                        rec.set(this.dataIndex, newValue);
                    }, this);
                }
                if (task.taskRunCount > times) {
                    column.renderHeaderCheck();
                    this.grid.getView().updateHeaders();
                    return false;
                }
            },
            interval: 1,
            scope: this
        };
        Ext.TaskMgr.start(task);
    },

    setAllColumn: function(columnIndex, newValue) {
        var colModel = this.grid.getColumnModel();
        var colId = colModel.getColumnId(columnIndex);
        var column = colModel.getColumnById(colId);
        this.internalSetAllColumn(column, newValue);
        this.grid.getView().updateHeaders();
    }
};

// -----------------------------------------
// End of plugin - Beginning of example code
// -----------------------------------------

        var chkColCountry = new Ext.grid.CheckColumn({ dataIndex: 'State.After', width: 50, headerCheck: true });

        var dsCountries = new Ext.data.ArrayStore({
            fields: ['Id', 'Name']
            , data: [["US","United States"],["CA","Canada"],["AF","Afghanistan"],["AL","Albania"],["DZ","Algeria"],["DS","American Samoa"],["AD","Andorra"],["AO","Angola"],["AI","Anguilla"],["AQ","Antarctica"],["AG","Antigua and/or Barbuda"],["AR","Argentina"],["AM","Armenia"],["AW","Aruba"],["AU","Australia"],["AT","Austria"],["AZ","Azerbaijan"],["BS","Bahamas"],["BH","Bahrain"],["BD","Bangladesh"],["BB","Barbados"],["BY","Belarus"],["BE","Belgium"],["BZ","Belize"],["BJ","Benin"],["BM","Bermuda"],["BT","Bhutan"],["BO","Bolivia"],["BA","Bosnia and Herzegovina"],["BW","Botswana"],["BV","Bouvet Island"],["BR","Brazil"],["IO","British lndian Ocean Territory"],["BN","Brunei Darussalam"],["BG","Bulgaria"],["BF","Burkina Faso"],["BI","Burundi"],["KH","Cambodia"],["CM","Cameroon"],["CV","Cape Verde"],["KY","Cayman Islands"],["CF","Central African Republic"],["TD","Chad"],["CL","Chile"],["CN","China"],["CX","Christmas Island"],["CC","Cocos (Keeling) Islands"],["CO","Colombia"],["KM","Comoros"],["CG","Congo"],["CK","Cook Islands"],["CR","Costa Rica"],["HR","Croatia (Hrvatska)"],["CU","Cuba"],["CY","Cyprus"],["CZ","Czech Republic"],["DK","Denmark"],["DJ","Djibouti"],["DM","Dominica"],["DO","Dominican Republic"],["TP","East Timor"],["EC","Ecudaor"],["EG","Egypt"],["SV","El Salvador"],["GQ","Equatorial Guinea"],["ER","Eritrea"],["EE","Estonia"],["ET","Ethiopia"],["FK","Falkland Islands (Malvinas)"],["FO","Faroe Islands"],["FJ","Fiji"],["FI","Finland"],["FR","France"],["FX","France, Metropolitan"],["GF","French Guiana"],["PF","French Polynesia"],["TF","French Southern Territories"],["GA","Gabon"],["GM","Gambia"],["GE","Georgia"],["DE","Germany"],["GH","Ghana"],["GI","Gibraltar"],["GR","Greece"],["GL","Greenland"],["GD","Grenada"],["GP","Guadeloupe"],["GU","Guam"],["GT","Guatemala"],["GN","Guinea"],["GW","Guinea-Bissau"],["GY","Guyana"],["HT","Haiti"],["HM","Heard and Mc Donald Islands"],["HN","Honduras"],["HK","Hong Kong"],["HU","Hungary"],["IS","Iceland"],["IN","India"],["ID","Indonesia"],["IR","Iran (Islamic Republic of)"],["IQ","Iraq"],["IE","Ireland"],["IL","Israel"],["IT","Italy"],["CI","Ivory Coast"],["JM","Jamaica"],["JP","Japan"],["JO","Jordan"],["KZ","Kazakhstan"],["KE","Kenya"],["KI","Kiribati"],["KP","Korea, Democratic People's Republic of"],["KR","Korea, Republic of"],["KW","Kuwait"],["KG","Kyrgyzstan"],["LA","Lao People's Democratic Republic"],["LV","Latvia"],["LB","Lebanon"],["LS","Lesotho"],["LR","Liberia"],["LY","Libyan Arab Jamahiriya"],["LI","Liechtenstein"],["LT","Lithuania"],["LU","Luxembourg"],["MO","Macau"],["MK","Macedonia"],["MG","Madagascar"],["MW","Malawi"],["MY","Malaysia"],["MV","Maldives"],["ML","Mali"],["MT","Malta"],["MH","Marshall Islands"],["MQ","Martinique"],["MR","Mauritania"],["MU","Mauritius"],["TY","Mayotte"],["MX","Mexico"],["FM","Micronesia, Federated States of"],["MD","Moldova, Republic of"],["MC","Monaco"],["MN","Mongolia"],["MS","Montserrat"],["MA","Morocco"],["MZ","Mozambique"],["MM","Myanmar"],["NA","Namibia"],["NR","Nauru"],["NP","Nepal"],["NL","Netherlands"],["AN","Netherlands Antilles"],["NC","New Caledonia"],["NZ","New Zealand"],["NI","Nicaragua"],["NE","Niger"],["NG","Nigeria"],["NU","Niue"],["NF","Norfork Island"],["MP","Northern Mariana Islands"],["NO","Norway"],["OM","Oman"],["PK","Pakistan"],["PW","Palau"],["PA","Panama"],["PG","Papua New Guinea"],["PY","Paraguay"],["PE","Peru"],["PH","Philippines"],["PN","Pitcairn"],["PL","Poland"],["PT","Portugal"],["PR","Puerto Rico"],["QA","Qatar"],["RE","Reunion"],["RO","Romania"],["RU","Russian Federation"],["RW","Rwanda"],["KN","Saint Kitts and Nevis"],["LC","Saint Lucia"],["VC","Saint Vincent and the Grenadines"],["WS","Samoa"],["SM","San Marino"],["ST","Sao Tome and Principe"],["SA","Saudi Arabia"],["SN","Senegal"],["SC","Seychelles"],["SL","Sierra Leone"],["SG","Singapore"],["SK","Slovakia"],["SI","Slovenia"],["SB","Solomon Islands"],["SO","Somalia"],["ZA","South Africa"],["GS","South Georgia South Sandwich Islands"],["ES","Spain"],["LK","Sri Lanka"],["SH","St. Helena"],["PM","St. Pierre and Miquelon"],["SD","Sudan"],["SR","Suriname"],["SJ","Svalbarn and Jan Mayen Islands"],["SZ","Swaziland"],["SE","Sweden"],["CH","Switzerland"],["SY","Syrian Arab Republic"],["TW","Taiwan"],["TJ","Tajikistan"],["TZ","Tanzania, United Republic of"],["TH","Thailand"],["TG","Togo"],["TK","Tokelau"],["TO","Tonga"],["TT","Trinidad and Tobago"],["TN","Tunisia"],["TR","Turkey"],["TM","Turkmenistan"],["TC","Turks and Caicos Islands"],["TV","Tuvalu"],["UG","Uganda"],["UA","Ukraine"],["AE","United Arab Emirates"],["GB","United Kingdom"],["UM","United States minor outlying islands"],["UY","Uruguay"],["UZ","Uzbekistan"],["VU","Vanuatu"],["VA","Vatican City State"],["VE","Venezuela"],["VN","Vietnam"],["VG","Virigan Islands (British)"],["VI","Virgin Islands (U.S.)"],["WF","Wallis and Futuna Islands"],["EH","Western Sahara"],["YE","Yemen"],["YU","Yugoslavia"],["ZR","Zaire"],["ZM","Zambia"],["ZW","Zimbabwe"]]
            , autoLoad: false
        });

        var cmCountry = new Ext.grid.ColumnModel([
            chkColCountry
            , { id: 'Id', header: 'Id', dataIndex: 'Id', width: 40 }
            , { id: 'Name', header: 'CountryName', dataIndex: 'Name', width: 460 }
            , { id: 'After', header: 'After', dataIndex: 'State.After', hidden: true }
        ]);

        var grdCountries = new Ext.grid.GridPanel({
            store: dsCountries
            , cm: cmCountry
            , plugins: chkColCountry
            , enableHdMenu: false
        });

        var win = new Ext.Window({
          layout: 'fit'
          , height: 190
          , width: 600
          , items: [grdCountries]
        });
        win.show();
<link href="//cdnjs.cloudflare.com/ajax/libs/extjs/3.4.1-1/resources/css/ext-all.css" rel="stylesheet"/>
<script src="//cdnjs.cloudflare.com/ajax/libs/extjs/3.4.1-1/adapter/ext/ext-base.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/extjs/3.4.1-1/ext-all.js"></script>

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top