Q:

swap rows in Ext.grid.Panel

I have grid with two buttons: "up row" and "down row".
Ext.define('OrionWebClient.controller.Request', {
    extend: 'Ext.app.Controller',
    refs:[
        {ref:'list',selector:'requestlist'}
    ],
    init: function() {
        this.control('requestlist',{
            itemclick: this.OnItemClick,
        });
        this.control('requestlist toolbar button[iconCls=btnUp]',{
            click: this.OnButtonUpRequest
        });
        this.control('requestlist toolbar button[iconCls=btnDown]',{
            click: this.OnButtonDownRequest
        });

        this._cur_index=-1;
    },

    OnItemClick:function (grid,rec,item,index) {
        this.SetCurrentIndex(index,false);
    },

    OnButtonUpRequest:function () {
        var index=this.GetCurrentIndex();
        if (index==-1){
            var max_i=this.GetMaxIndex();
            this.SetCurrentIndex(max_i,true);
            return;
        }
        if (index==0){
            return;
        }
        this.SwapRow(index,index-1);
        this.SetCurrentIndex(index-1,true);
    },

    OnButtonDownRequest:function () {
        var index=this.GetCurrentIndex()
        if (index==-1){
            //var max_i=GetMaxIndex();
            this.SetCurrentIndex(0,true);
            return;
        }
        if (index==this.GetMaxIndex()){
            return;
        }
        this.SwapRow(index,index+1);
        this.SetCurrentIndex(index+1,true);
        //console.log("down");
    },

    GetCurrentIndex:function (){
        return this._cur_index;        
    },
    SetCurrentIndex:function (index,visual) {
        if (visual){
            var list=this.getList();
            list.getSelectionModel().select(index);
        }
        this._cur_index=index;
    },
    GetMaxIndex:function () {
        var store=this.getList().getStore();
        return store.count()-1;
    },
    SwapRow:function (cur_index,new_index){
        var store=this.getList().getStore();
        var rec=store.getAt(cur_index).copy();

        console.log(store.data); 
        //store.removeAt(cur_index);
        //store.insert(new_index,[rec]);

    }

});

Ext.define('OrionWebClient.view.RequestList',{
    extend: 'Ext.grid.Panel',
    id:'rqstlst',
    title:'Request List',
    alias:'widget.requestlist',
    border:true,
    requires:['OrionWebClient.model.Request'],    
    columns:{
        defaults:{
            draggable:false,
            sortable:false,
            hideable:false,
            resizable:false
        },
        items:[
            { text: '#', xtype:'rownumberer',width:30 },
            { text: 'command', dataIndex: 'cmd',width:250},
            { text: 'params', dataIndex: 'args',width:250},
            { text: '*', dataIndex: 'check',xtype: 'checkcolumn',width:30 }
        ]
    },
    store:{
        model: 'OrionWebClient.model.Request',
        autoLoad:true
    },
    dockedItems: [
        {
            xtype: 'toolbar',
            dock: 'bottom',
            defaults: {
                maxWidth: 90, 
                type:'button',
                margin:'1 5 1 5'
            },
            items: [
                { text: 'Up',iconCls:'btnUp'},
                { text: 'Down',iconCls:'btnDown'},
                '-',
            ]
        }
    ]
});

But I don't undestand how manipulate order rows in store, and swap two rows. I don't like use:
var store=getList().getStore();
var rec=store.getAt(index).copy();
store.removeAt(index);
store.insert(index,rec);

I think that is bad solution.
P.S.
Sorry, my english is not good.

A:

first you are right: the order of row in a grid can only be changed in the store.
looking through all methods of the Store the you have no other choice except remove one record and reinsert it again.
But its importent to call store.suspendAutoSync() before and store.resumeAutoSync() after the swap if you have store.autoLoad = true so nothing gets send to the server.
You can also try this nice plugin: Ext.grid.plugin.DragDrop for Drag'n'Drop reorder of rows.
PS: Use store.remove(rec) instead of store.removeAt(index) cause removeAt will call remove internally.

