在 Angular 2 中预先打开分支时保持树视图行为

Maintain treeview behaviour when branch is pre-opened in Angular 2

我有一个递归树视图组件,它从第三方加载数据 API。它运作良好。不过,我现在要做的是在首次渲染树时在特定分支处打开树(从长远来看,这将挂接到路由参数中,因此可以通过调用不同的 URL,但婴儿先一步......)。

树中的每个分支都有一个唯一的 ID。我已经将其中一个分支的 id 硬编码到组件中,并在模板循环中检查循环中当前分支的值是否匹配,如果匹配,它会在该分支打开树。

组件代码如下:

import { Component, Input, OnInit } from '@angular/core';
import { Router, RouteSegment }     from '@angular/router';

import { ContentNode }              from './content-node';
import { ContentService }           from '../services/content.service';


@Component({
    selector: 'content-tree',
    directives: [ContentTreeComponent],
    template: `
        <ol class="tree">
            <li *ngFor="let contentNode of contentNodes" class="tree__branch" [ngClass]="{'tree__branch--has-children': contentNode.HasChildren}">
                <a *ngIf="contentNode.HasChildren" (click)="contentNode.toggle=!contentNode.toggle" class="tree__branch__toggle">
                    {{ !!contentNode.toggle || openNode == contentNode.Id ? '-' : '+' }}
                </a> 
                <a class="tree__branch__link" (click)="onSelect(contentNode)">{{ contentNode.Name }}</a>
                <content-tree *ngIf="contentNode.toggle || openNode == contentNode.Id" [startNodeId]="contentNode.Id"></content-tree>
            </li>
        </ol>
        <div class="error" *ngIf="errorMessage">{{errorMessage}}</div>
    `
})
export class ContentTreeComponent implements OnInit {

  openNode = 1054;

    constructor(
        private _contentService: ContentService,
        private _router: Router,
        private _currSegment: RouteSegment
    ) { }

    errorMessage: string;

    @Input('startNodeId')
    private _startNodeId: number;

    contentNodes: ContentNode[];

    ngOnInit() { 
        this.getContentNodes();
    }

    onSelect(contentNode: ContentNode) {
        this._router.navigate([`./${contentNode.Id}`], this._currSegment);
    }

    getContentNodes() {
        this._contentService.getContentNodes(this._startNodeId)
            .subscribe(
                contentNodes => this.contentNodes = contentNodes,
                error =>  this.errorMessage = <any>error
            );
    }
}

Here's a plunkr.

这工作正常......几乎!单击左侧红色菜单中的 'Content',您将看到树视图。请注意树中的第一个分支 (Rugby League) 是打开的,这是正确的(它的 ID 为 1054,我在组件中对其进行了硬编码以确保它打开)但是这个分支现在似乎失去了它的行为;它不能再通过单击左侧的 - link 来关闭。如果您从模板中删除 || openNode == contentNode.Id,它会 opens/closes 正确。树中的其他分支保持其行为,但不是这个。

谁能建议即使以编程方式打开分支时如何保持树的行为?

非常感谢您对此提供的任何帮助!

这是正确的行为,因为您 *ngIf 的第二部分始终为真。

您的 "Rugby League" 树有两种状态:切换和未切换

1- 未切换:*ngIf="false || 1054 == 1054" > *ngIf="false || true" > *ngIf="true"

2- 切换:*ngIf="true || 1054 == 1054" > *ngIf="true || true" > *ngIf="true"

如您所见,*ngIf 表达式的计算结果始终为真。


如何修复:

我删除了 || openNode == contentNode.Id 并更改了您的 getContentNodes() 以将节点设置为在获取后切换。

getContentNodes() {
    this._contentService.getContentNodes(this._startNodeId)
        .subscribe(
            contentNodes => {
              this.contentNodes = contentNodes;
              this.contentNodes.filter(n=>n.Id === this.openNode).forEach(n=>n.toggle = true);  // I added this line
            },
            error =>  this.errorMessage = <any>error
        );
}

Here is you plunk fixed