1

我正在创建一个带有两个框的项目选择器,它们在 extjs 应用程序中来回移动事物。在右侧框中,我正在创建用于上下移动项目的按钮。本质上,我正在将项目与它上方或下方的项目交换。所以,我的代码在这方面是直截了当的

MoveUp: function(button, event, eOpts){
  var theChosen = Ext.getStore('storeId').getRootNode().findChild('text', 'Chosen folder');
  var chosenPanel = Ext.ComponenetQuery.query('#chosenTreePanel')[0];
  var selected = chosenPanel.getSelectionModel().getSelection();

  for( var i = 1; i < theChosen.childNodes.length; i++){
    if(Ext.Array.contains(selected, theChosen.childNodes[i]) && (!Ext.Array.contains(selected, theChosen.childNodes[i-1]){
      var temp = theChosen.childNodes[i];
      theChosen.childNodes[i] = theChosen.childNodes[i-1];
      theChosen.childNodes[i-1] = temp;

    }

  }
}

所有这些代码似乎都可以正常工作,因为单击我的按钮并在 firebug 中检查 DOM 后,我可以看到所选节点已正确移动到数组中,但是,这种效果从未显示在我的树形面板中。???当它的元素发生变化时,如何使树形面板更新。???

TreePanel 层次结构看起来像这样只是为了澄清

根节点“选择的文件夹节点”我在“文件夹”中上下移动的项目数组

我正在使用版本 4.0.7

尝试使用 replaceChild() 触发事件以重新渲染的行为不像我预期的那样

改变:

var temp = theChosen.childNodes[i];
theChosen.childNodes[i] = theChosen.childNodes[i-1];
theChosen.childNodes[i-1] = temp;

至:

var temp = theChosen.childNodes[i];
theChosen.replaceChild(theChosen.childNodes[i-1], theChosen.childNodes[i]);
theChosen.replaceChild(temp, theChosen.childNodes[i-1]);

导致一些节点丢失的奇怪行为。当然不是我想要的。我在哪里错了?

使用 datachanged 和(未记录的)刷新事件尝试了以下代码:

Ext.getStore('storeId').fireEvent('datachanged', Ext.getStore('chosen') );
Ext.getStore('storeId').fireEvent('datachanged', Ext.getStore('chosen') );

这不会重新加载任何东西......

解决方案:

使用 nodeInterface 的 insertChild 方法......

我注意到 insertChild 的工作方式有些奇怪,因为我需要更多地基于向上或向下移动来更改我的索引,这将在下面的代码中进行解释。

向上移动:

theChosen.insertChild( (i-1), theChosen.childNodes[i]);

向下移动:

theChosen.insertChild( (i+2), theChosen.childNodes[i]);

尽管 -1 与 +2 他们都有效地将项目向适当的方向移动了一个。

4

2 回答 2

5

如果要更新节点的视图,我建议使用 yourTree.getView().refresh();

但是您可以通过使用 parentNode.insertChild(index, childNode); 来避免这种情况。其中 index 是您希望节点显示的位置,而 parentNode 是您正在重新排序的节点的父节点。ChildNode 可以是新节点或任何其他已存在的节点接口的配置。如果节点已经存在并且您使用 insertChild 方法插入它,它将自动从其他任何地方删除该节点。

因此,正如您在回答我的回答时在问题中提供的那样,您的代码将使用类似的东西(这可能是我的做法,但未经测试):

MoveUp: function(button, event, eOpts){
    var chosenPanel = Ext.ComponenetQuery.query('#chosenTreePanel')[0];
    var selectedNodes = chosenPanel.getSelectionModel().getSelection();
    for( var i = 0; i < selectedNodes.length; i++){
        var currentNode = selectedNodes[i];
        if(!currentNode.isFirst())
        {
            var parentNode = currentNode.parentNode;
            var newIndex = parentNode.indexOf(currentNode) - 1;
            parentNode.insertChild(newIndex, currentNode);
        }
    }
}
于 2012-09-06T13:30:27.727 回答
1

编辑:

回到负责任的事件问题...您需要触发

'datachanged' 
'refresh'

商店上的事件,商店仅作为参数。这应该会导致 UI 更新。但请注意,我只是瞥了一眼源代码,我相信这一切都可以做得更聪明。至少已经存在一个DD 解决方案。如果我找到一些时间,我会再次对此进行调查,但我想您首先应该对这些事件感到满意。

您永远看不到任何东西,因为您只是在没有适当方法的情况下执行此操作,然后触发导致重新渲染的负责任事件。看一眼

可能还有更多方法可以帮助Ext.data.NodeInterface。我建议您使用这些,而不是在没有触发任何负责任事件的情况下在引擎盖下进行。

除了我的第二条评论(只是一个疯狂的猜测,不知道这是否正是你想要的):

MoveUp: function(button, event, eOpts){
    var target = Ext.getStore('storeId').getRootNode().findChild('text', 'Chosen folder');
    var selected = chosenPanel.getSelectionModel().getSelection();
    target.appendChild(selected);
}
于 2012-09-06T12:10:14.733 回答