等待图标的长过程块在ExtJS中呈现

时间:2010-07-30 20:35:05

标签: extjs rendering blocking animated-gif long-running-processes

我正在实现的功能并不是真正需要的,因此我不会为此添加额外的线程库。但如果有人知道解决方法,我会很感激。

所以我有一个256行3列的网格;其中一列是 checkboxColumn (类似于使用的here)。但该checkboxColumn插件已被修改为在标题中显示一个复选框,以便允许某种Check-AllCheck-None功能。

因为行数太多,所以检查所有过程都需要很长时间。所以我决定放一个“旋转轮”(等待gif动画)。现在的问题是动画不起作用。所以我进行了defer调用以允许渲染动画图标,但似乎defer不足以让动画运行。虽然这个defer至少允许显示等待gif的第一帧,而不是显示大约一分钟的检查状态,直到完成所有操作后显示未检查状态。

这是一种昂贵的方法:

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);
}

您可以在以下代码段中看到一个有效的示例:

/*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>

单击列复选框(标题上的那个)并查看未旋转的gif as expected

注意:我在其他地方有分页功能,但我不会在这里使用它,因为256行总是相同的。所以我宁愿失去check all按钮而不是分页。

3 个答案:

答案 0 :(得分:3)

问题不在于使用.defer(),而是在错误的级别上进行。导致冻结的紧密循环是导致冻结的原因,并且您实际上并没有将这些UI更新卸载到另一个线程,您只是推迟了循环的执行。当循环在50毫秒后启动时,它仍然是一个需要一段时间才能执行的紧密循环。

这是一个快速解决方案,虽然不是最佳的,但可能更接近你想要的东西:

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

一些笔记。如果您使用defer只是在另一个线程上执行代码(而不是真正因为您需要特定的延迟),只需使用1 ms。无需等待更长时间。

其次,要注意使用这样的延迟 - 它可能适用于这种情况,但这不是一般的最佳实践。当你开始推迟东西时(特别是在像这样的循环中),如果在循环中间执行其他代码也可能影响你的底层商店,它可能会导致问题。理想情况下,您可以找到一个更合适的解决方案,例如仅推迟网格的UI更新,但我怀疑这样做可能需要覆盖或两个(不确定在我的头顶)。所以,如果这能为你解决这个问题,那很好 - 但是不要说我没有警告你,如果以后弹出一些其他奇怪的错误;​​)

顺便说一下,如果你在网格中向下滚动,由于循环仍然从上到下执行,因此用户仍然会有明显的延迟。您可以先了解并更新可见记录,然后再转到其他数据集 - 取决于您想要投入多少精力。

编辑:好了,在对此进行了一些考虑之后,您需要做的就是避免UI更新,告诉商店不要在循环期间触发其更新事件,然后手动刷新完成所有数据更新后的网格。使用这种方法,您甚至不需要在标题中使用微调器,并且可以避免defer的所有潜在问题。试试这个:

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();
}

答案 1 :(得分:0)

尝试使用Ext.TaskMgr而不是使用延迟,它允许您创建任务并以多线程方式运行它。

任务示例。

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

答案 2 :(得分:0)

可能太棘手了,但确实显示了动画旋转轮,看起来效果很好:

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>