Extjs使用复选框模型在网格上拖放单个项目

时间:2013-08-28 02:00:59

标签: javascript extjs checkbox drag-and-drop grid

我将以下示例代码修改为复选框模型。链接在这里 http://docs.sencha.com/extjs/4.2.1/#!/api/Ext.grid.plugin.DragDrop

首先是两个问题:
拖动项目时,也会移动所有选定的项目。如何每次只拖动一个项目?

另一个问题:
拖动项目时,会强制选择该项目。如何让它保持状态不变? (在拖动之前取消选择时保持未选中状态,反之亦然)

我使用的是版本4.2.1。

以下是从给定示例修改的代码:

Ext.onReady(function () {
    Ext.create('Ext.data.Store', {
        storeId: 'simpsonsStore',
        fields: ['name'],
        data: [
            ["Lisa"],
            ["Bart"],
            ["Homer"],
            ["Marge"]
        ],
        proxy: {
            type: 'memory',
            reader: 'array'
        }
    });

    Ext.create('Ext.grid.Panel', {
        store: 'simpsonsStore',
        selModel: {mode: 'SIMPLE'}, //added
        selType: 'checkboxmodel', //added
        columns: [{
            header: 'Name',
            dataIndex: 'name',
            flex: true
        }],
        viewConfig: {
            plugins: {
                ptype: 'gridviewdragdrop',
                dragText: 'Drag and drop to reorganize'
            }
        },
        height: 200,
        width: 400,
        renderTo: Ext.getBody()
    });
});

谢谢!

3 个答案:

答案 0 :(得分:3)

  1. 您需要在DragDrop插件中覆盖dragZone,因此它只发送此记录。

  2. 拖动有一个mousedown事件,它正在选择网格中的行(因为它也有一个mousedown事件),所以在拖动结束之前它被触发。

  3. 为了理解这一点,我解释了这些事件(更多信息w3schools

    1. 行选择事件:这是网格行上的 mousedown 事件。
    2. drag事件: drag = mousepress + (可选) mousemove ,但是:mousepress实际上并不存在,所以它借助于mousedown和mouseup之间的时间
      • 使用delayedTasks
      • 完成时间测量
      • 如果mouseup在延迟时间之前触发,则不会执行,否则拖动开始
    3. drop事件: drop = dragged + mouseup

      有更多方法可以防止这种情况:

      1. 尝试将选择放到另一个事件中,该事件在拖动开始后被触发,但它可能会很乱,因为此事件被多次使用...
      2. 它在mousedown上选择它,但是我们在拖动开始事件中取消选择它,然后我们阻止选择,我在代码中执行此操作
    4. 工作代码:

      Ext.create('Ext.data.Store', {
          storeId:'simpsonsStore',
          fields:['name'],
          data: [["Lisa"], ["Bart"], ["Homer"], ["Marge"]],
          proxy: {
              type: 'memory',
              reader: 'array'
          }
      });
      
      Ext.create('Ext.grid.Panel', {
          store: 'simpsonsStore',
          selModel: {mode: 'SIMPLE'}, //added
          selType: 'checkboxmodel', //added
          columns: [
              {header: 'Name',  dataIndex: 'name', flex: true}
          ],
          viewConfig: {
              plugins: {
                  ptype: 'gridviewdragdrop',
                  dragText: 'Drag and drop to reorganize',
                  onViewRender : function(view) {
                      var me = this,
                          scrollEl;
                      if (me.enableDrag) {
                          if (me.containerScroll) {
                              scrollEl = view.getEl();
                          }                   
                          me.dragZone = new Ext.view.DragZone({
                              view: view,
                              ddGroup: me.dragGroup || me.ddGroup,
                              dragText: me.dragText,
                              containerScroll: me.containerScroll,
                              scrollEl: scrollEl,
                              //to remember if the row was selected originally or not
                              onBeforeDrag: function(data, e) {                            
                                  var me = this,                               
                                      view = data.view,
                                      selectionModel = view.getSelectionModel(),
                                      record = view.getRecord(data.item);
                                  if (!selectionModel.isSelected(record)) {
                                      data.rowSelected = false;
                                  } 
                                  return true;
                              },
      
                              onInitDrag: function(x, y) {
                                  var me = this,
                                      data = me.dragData,
                                      view = data.view,
                                      selectionModel = view.getSelectionModel(),
                                      record = view.getRecord(data.item);
                                  //for deselect the dragged record
                                  if (selectionModel.isSelected(record) && data.rowSelected == false) {
                                      selectionModel.deselect(record, true);                                
                                  }
                                  //added the original row so it will handle that in the drag drop
                                  data.records = [record];                            
                                  me.ddel.update(me.getDragText());
                                  me.proxy.update(me.ddel.dom);
                                  me.onStartDrag(x, y);
                                  return true;
                              }
                          });
                      }
      
                      if (me.enableDrop) {
                          me.dropZone = new Ext.grid.ViewDropZone({
                              view: view,
                              ddGroup: me.dropGroup || me.ddGroup,
                              //changed the selection at the end of this method
                              handleNodeDrop : function(data, record, position) {
                                  var view = this.view,
                                      store = view.getStore(),
                                      index, records, i, len;
      
                                  if (data.copy) {
                                      records = data.records;
                                      data.records = [];
                                      for (i = 0, len = records.length; i < len; i++) {
                                          data.records.push(records[i].copy());
                                      }
                                  } else {                                
                                      data.view.store.remove(data.records, data.view === view);
                                  }                    
                                  if (record && position) {
                                      index = store.indexOf(record);
                                      if (position !== 'before') {
                                          index++;
                                      }
                                      store.insert(index, data.records);
                                  }                            
                                  else {
                                      store.add(data.records);
                                  }
                                  if (view != data.view) {
                                      view.getSelectionModel().select(data.records);
                                  }                                                   
                              }
                          });
                      }
                  }
              }        
          },
          height: 200,
          width: 400,
          renderTo: Ext.getBody()
      });

答案 1 :(得分:0)

感谢亚历山大的回复。在阅读完回复后,我进入了相关的Extjs源代码。最后解决了立即改变状态的问题,而不是让它保持不变。代码:

Ext.onReady(function () {
    Ext.create('Ext.data.Store', {
        storeId: 'simpsonsStore',
        fields: ['name'],
        data: [
            ["Lisa"],
            ["Bart"],
            ["Homer"],
            ["Marge"]
        ],
        proxy: {
            type: 'memory',
            reader: 'array'
        }
    });

    Ext.create('Ext.grid.Panel', {
        store: 'simpsonsStore',
        /* Start: Code block added to the original example */
        selModel: {mode: 'SIMPLE', onRowMouseDown: Ext.emptyFn /* throw away onRowMouseDown handler to answer Q2 */},
        selType: 'checkboxmodel', 
        listeners: {
            afterrender: function(){
                /* override the original handleNodeDrop function to answer Q1 */
                this.view.plugins[0].dropZone.handleNodeDrop = function(data, record, position) {
                    var view = this.view,
                    store = view.getStore(),
                    index, records, i, len;

                    if (data.copy) {
                        records = data.records;
                        data.records = [];
                        for (i = 0, len = records.length; i < len; i++) {
                            data.records.push(records[i].copy());
                        }
                    } else {
                        data.view.store.remove(data.records, data.view === view);
                    }

                    if (record && position) {
                        index = store.indexOf(record);

                        if (position !== 'before') {
                            index++;
                        }
                        store.insert(index, data.records);
                    }
                    else {
                        store.add(data.records);
                    }

                    // view.getSelectionModel().select(data.records);
                };
                /* override the original onInitDrag function to answer Q2 */
                this.view.plugins[0].dragZone.onInitDrag = function(x, y){
                    var me = this,
                    data = me.dragData,
                    view = data.view,
                    selectionModel = view.getSelectionModel(),
                    record = view.getRecord(data.item);

                    // if (!selectionModel.isSelected(record)) {
                        // selectionModel.select(record, true);
                    // }
                    // data.records = selectionModel.getSelection();
                    data.records = [selectionModel.lastFocused];

                    me.ddel.update(me.getDragText());
                    me.proxy.update(me.ddel.dom);
                    me.onStartDrag(x, y);
                    return true;
                };
            }
        }, 
        /* End: Code block added to the original example */
        columns: [{
            header: 'Name',
            dataIndex: 'name',
            flex: true
        }],
        viewConfig: {
            plugins: {
                ptype: 'gridviewdragdrop',
                dragText: 'Drag and drop to reorganize'
            }
        },
        height: 200,
        width: 400,
        renderTo: Ext.getBody()
    });
});

答案 2 :(得分:0)

如果有人对 4.1.1 解决方案感兴趣,这里是修改后的 Alexander 代码,它在删除后保持先前选择的行。

我稍微修改了 onInitDrag 以在拖动开始时选择已经选择的行, 和 handleNodeDrop 以使其在放置时被选中。

Ext.create('Ext.data.Store', {
    storeId:'simpsonsStore',
    fields:['name'],
    data: [["Lisa"], ["Bart"], ["Homer"], ["Marge"]],
    proxy: {
        type: 'memory',
        reader: 'array'
    }
});

Ext.create('Ext.grid.Panel', {
    store: 'simpsonsStore',
    selModel: {mode: 'SIMPLE'}, //added
    selType: 'checkboxmodel', //added
    columns: [
        {header: 'Name',  dataIndex: 'name', flex: true}
    ],
    resizable: true,
    viewConfig: {
        plugins: {
            ptype: 'gridviewdragdrop',
            dragText: 'Drag and drop to reorganize',
            onViewRender : function(view) {
                var me = this,
                    scrollEl;
                if (me.enableDrag) {
                    if (me.containerScroll) {
                        scrollEl = view.getEl();
                    }                   
                    me.dragZone = new Ext.view.DragZone({
                        view: view,
                        ddGroup: me.dragGroup || me.ddGroup,
                        dragText: me.dragText,
                        containerScroll: me.containerScroll,
                        scrollEl: scrollEl,
                        //to remember if the row was selected originally or not
                        onBeforeDrag: function(data, e) {                            
                            var me = this,                               
                                view = data.view,
                                selectionModel = view.getSelectionModel(),
                                record = view.getRecord(data.item);
                            if (!selectionModel.isSelected(record)) {
                                data.rowSelected = false;
                            } else {
                                data.rowSelected = true;
                            }
                            return true;
                        },

                        onInitDrag: function(x, y) {
                            var me = this,
                                data = me.dragData,
                                view = data.view,
                                selectionModel = view.getSelectionModel(),
                                record = view.getRecord(data.item);
                            //to deselect the dragged record
                            if (selectionModel.isSelected(record) && data.rowSelected == false) {
                                selectionModel.deselect(record, true); 
                            } else {
                                selectionModel.select(record, true); 
                            }
                            //added the original row so it will handle that in the drag drop
                            data.records = [record];                            
                            me.ddel.update(me.getDragText());
                            me.proxy.update(me.ddel.dom);
                            me.onStartDrag(x, y);
                            
                            return true;
                        }
                    });
                }

                if (me.enableDrop) {
                    me.dropZone = new Ext.grid.ViewDropZone({
                        view: view,
                        ddGroup: me.dropGroup || me.ddGroup,
                        //changed the selection at the end of this method
                        handleNodeDrop : function(data, record, position) {
                            var view = this.view,
                                store = view.getStore(),
                                selectionModel = view.getSelectionModel(),
                                index, records, i, len;

                            if (data.copy) {
                                records = data.records;
                                data.records = [];
                                for (i = 0, len = records.length; i < len; i++) {
                                    data.records.push(records[i].copy());
                                }
                            } else {                                
                                data.view.store.remove(data.records, data.view === view);
                            }        
                            
                            if (record && position) {
                                index = store.indexOf(record);
                                if (position !== 'before') {
                                    index++;
                                 }
                                store.insert(index, data.records);
                            }                            
                            else {
                                store.add(data.records);
                            }
                            
                            //select row back on drop if it was selected
                            if (data.rowSelected) {
                                selectionModel.select(data.records, true);
                            }

                            if (view != data.view) {
                                view.getSelectionModel().select(data.records);
                            }          
                        }
                    });
                }
            }
        }        
    },
    height: 200,
    width: 400,
    renderTo: Ext.getBody()
});

PS:最简单的测试方法 - https://fiddle.sencha.com/#view/editor 只需选择 4.1.1 并复制粘贴。