AngularTreeComponent: TreeModel.update() работает асинхронно. Как дождаться готового обновления?

#angular #asynchronous #angular-tree-component

#angular #асинхронный #angular-tree-component

Вопрос:

Мне нужно заменить некоторые данные в дереве, затем запустить treemodel.update() и после этого выбрать узел. Дерево уже отображается в это время. Это мой код:

     @ViewChild('resulttree') resulttree: ElementRef;
    
    updateResulttree(id: number) {
        for (let node of this.resultNodes) {
          node.children[0].children = node.children[0].children.filter(childnode => childnode.selected);
          node.children[1].children = node.children[1].children.filter(childnode => childnode.selected);
        }        
    
        this.resulttree.treeModel.update();
    
        setTimeout(() => {
            const someNode = this.resulttree.treeModel.getNodeBy(node => node.data.tree_node_id === id);
              someNode.setActiveAndVisible();
            }, 100); 
}
 

Эта работа с setTimeout работает, но это не хорошо. Если метод update() занимает более 100 мс, «someNode» будет неопределенным.

Есть идеи, как сделать это лучше?

Angular 10, AngularTreeCompoment 10.0.2 https://angular2-tree.readme.io/docs/getting-started

Ответ №1:

из их кода https://github.com/CirclonGroup/angular-tree-component/blob/master/projects/angular-tree-component/src/lib/models/tree.model.ts , вызов функции update() вызовет событие updateData по завершении, если это не первое обновление (чего не должно быть, если у вас уже есть отображаемое дерево), вы можете подписаться на это событие перед вызовом update() и выбрать свой узел в событииобработчик (не забудьте отписаться):

   @action update() {
    // Rebuild tree:
    let virtualRootConfig = {
      id: this.options.rootId,
      virtual: true,
      [this.options.childrenField]: this.nodes
    };

    this.dispose();

    this.virtualRoot = new TreeNode(virtualRootConfig, null, this, 0);

    this.roots = this.virtualRoot.children;

    // Fire event:
    if (this.firstUpdate) {
      if (this.roots) {
        this.firstUpdate = false;
        this._calculateExpandedNodes();
      }
    } else {
      this.fireEvent({ eventName: TREE_EVENTS.updateData });
    }
  }
 

Комментарии:

1. Проблема с этим решением заключается в том, что это событие также запускается в разных случаях. Из их руководства «Срабатывает после обновления древовидной модели либо путем изменения входных данных дерева (узлов, параметров и т. Д.), Либо Прямым вызовом update()». Я хочу выбрать узел только после прямого вызова update() .

2. если вы подписываетесь на событие прямо перед вызовом update, а затем отписываетесь, когда событие было вызвано, я думаю, это сделает то, что вам нужно.

3. Можете ли вы привести пример того, как правильно подписаться на событие? Я попробовал несколько предложений, но, похоже, ничего не работает. Моя переменная «resulttree» является дочерним элементом дерева.