Как упорядочить элементы узлов верхнего уровня в дереве диджита с помощью перетаскивания - PullRequest
2 голосов
/ 04 августа 2011

У меня есть dijit.Tree, подкрепленный ForestStoreModel, который использует пользовательское хранилище данных для предоставления данных.Это хорошо работает, но я хочу предоставить пользователю возможность переставлять элементы верхнего уровня (и только верхнего уровня) с помощью средства перетаскивания dojo.

Проблема в том, чтоФункция ForestStoreModel::pasteItem проверяет, является ли элемент дочерним элементом корня, а затем передает null в TreeStoreModel::pasteItem.

pasteItem: function(/*Item*/ childItem, /*Item*/ oldParentItem, /*Item*/ newParentItem, /*Boolean*/ bCopy, /*int?*/ insertIndex){
        // summary:
        //      Move or copy an item from one parent item to another.
        //      Used in drag & drop
        if(oldParentItem === this.root){
            if(!bCopy){
                // It's onLeaveRoot()'s responsibility to modify the item so it no longer matches
                // this.query... thus triggering an onChildrenChange() event to notify the Tree
                // that this element is no longer a child of the root node
                this.onLeaveRoot(childItem);
            }
        }
        dijit.tree.TreeStoreModel.prototype.pasteItem.call(this, childItem,
            oldParentItem === this.root ? null : oldParentItem,
            newParentItem === this.root ? null : newParentItem,
            bCopy,
            insertIndex
        );
        if(newParentItem === this.root){
            // It's onAddToRoot()'s responsibility to modify the item so it matches
            // this.query... thus triggering an onChildrenChange() event to notify the Tree
            // that this element is now a child of the root node
            this.onAddToRoot(childItem);
        }
    }

. TreeStoreModel не обновляет базовое хранилище данных, еслипереданные родительские элементы имеют значение null, а события onLeaveRoot и onAddToRoot не передаются в insertIndex, поэтому я не могу использовать их для обновления моего хранилища данных (в любом случае кажется, что это будет немного назад).

На данный момент я думаю, что единственно приемлемым вариантом является расширение ForestStoreModel, чтобы позволить мне установить синтетический элемент $root$ на совместимый объект хранилища данных и позволить ForestStoreModel передать его без изменений., вплоть до TreeStoreModel.

Есть ли другой способ решения этой проблемы?

Обновление

Возможное решение оказалось четнымпроще, чем предполагалось.Мой ForestStoreModel уже является пользовательским классом, потому что я на самом деле использую ObjectStore dojo 1.6 в качестве источника данных, поэтому я могу передать нужный индекс в аргументе options в метод store store put.Исправление было простым, поскольку я позволил родительскому классу позаботиться о вызовах onLeaveRoot и onAddRoot:

pasteItem: function(/*Item*/ childItem, /*Item*/ oldParentItem, /*Item*/ newParentItem, /*Boolean*/ bCopy, /*int?*/ insertIndex){
    // Handle drag & drop at the root level
    if (oldParentItem === this.root && newParentItem === this.root){
        this.store.put(childItem, { index: insertIndex });
    } 
    this.inherited(arguments);
}

1 Ответ

1 голос
/ 04 августа 2011

Вам нужно будет создать подкласс ForestTreeModel, вы не можете избежать этого.Но вам нужно только переопределить pasteItem.Вы не можете передать синтетический корень в TreeStoreModel, потому что он ничего об этом не знает.

Если вам нужно изменить базовое хранилище данных, лучше позвонить this.store.setValues() напрямую.Это должно вызвать событие onSetItem и, в свою очередь, вызвать для вас _requeryTop(), который будет извлекать корни из нижележащего хранилища в любом порядке, в котором вы их расположите, поэтому обязательно отразите это в вашей модификации.

dojo.declare('MyForestTreeModel', [ dijit.tree.ForestTreeModel ], {
  pasteItem: function(childItem, oldParentItem, newParentItem, bCopy, insertIndex) {
    if (oldParentItem == this.root && newParentItem == this.root) {
      if (!bCopy) { this.onLeaveRoot(childItem); }
      // modify the underlying store somehow so the call to _requeryTop() fetches
      // the items in the correct order.
      // (you decide what's 'order' and what new_order() returns)
      this.store.setValues(childItem, 'order', new_order(insertIndex));
      this.onAddRoot(childItem);
    } else {
      // call super
      this.inherited(arguments);
    }
  }
});

Другой, более простой способ - манипулировать this.root.children самостоятельно, а затем генерировать событие onChildrenChange для уведомления о взглядах.Осторожно, этот метод не сохранит порядок.

dojo.declare('MyForestTreeModel', [ dijit.tree.ForestTreeModel ], {
  pasteItem: function(childItem, oldParentItem, newParentItem, bCopy, insertIndex) {
    if (oldParentItem == this.root && newParentItem == this.root) {
      if (!bCopy) { this.onLeaveRoot(childItem); }
      // manipulate this.root.children to reorder childItem
      // remove child from the current position
      var children = dojo.filter(this.root.children, function(x) {
        return x != childItem;
      });
      // and insert it into the new index
      children.splice(insertIndex, 0, childItem);
      this.root.children = children;
      // notify views
      this.onChildrenChanged(this.root, children);
      this.onAddRoot(childItem);
    } else {
      // call super
      this.inherited(arguments);
    }
  }
});
...