当树节点展开或折叠时,我正在尝试更改树节点的图标。我成功地能够更改图标,但问题是树中的所有图标都发生了变化。我只想更改我点击的节点的图标。我的代码如下:
html文件
<div class="container sidenav-tree">
<ng-template #recursiveList let-files>
<div *ngFor="let item of files">
<div class="row node-item">
<i
data-toggle="collapse"
attr.data-target="#{{item.reference}}"
class="fa"
[ngClass]="{'fa-angle-down': isExpanded, 'fa-angle-right': !isExpanded}"
*ngIf="!(item.children.length===0)"
(click)="isExpanded=!isExpanded"></i>
{{item.name}}
</div>
<div id="{{item.reference}}" class="container collapse" *ngIf="!(item.children.length===0)">
<ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: item.children }"></ng-container>
</div>
</div>
</ng-template>
<ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: files }"></ng-container>
</div>
和组件文件:
import {Component, OnInit} from '@angular/core';
import {BlogService} from '../../../../services/blog.service';
@Component({
selector: 'app-sidenav',
templateUrl: './sidenav.component.html',
styleUrls: ['./sidenav.component.css'],
})
export class SidenavComponent implements OnInit {
files: [];
selectedFile: string;
selectedPath: string;
isExpanded = false;
constructor(private blogService: BlogService) {
}
ngOnInit() {
this.blogService
.getTreeNodes()
.subscribe((files: []) => {
console.log(files);
this.files = files;
});
}
nodeSelectEvent(event) {
this.blogService.selectedNode.next(event.target.innerText);
}
}
我希望尽可能在ts文件而不是组件文件中保留我的逻辑。请建议我的代码中所需的更改。
由于这似乎是一个任意深度递归树,最简单的事情是声明一个对象来建模你似乎要检索的文件列表,并在该实体上有一个描述它是否被展开的属性。
类似于添加到组件中的类
public export File{
Name:string;
isExanded:boolean;
}
然后我会改变你的文件数组
files:File[]
在订阅中加载数据时,您可以更新服务以使用类似的DTO对象并返回该集合,也可以循环遍历您获得的字符串列表并创建File对象实例。此时,您将isExanded选项初始化为false(除非您希望保留状态服务器端)。
然后,我将在树上实现一个事件处理程序,它更新了当前文件的状态
toggleFileState(item:File){
item.isExpanded = !item.isExpanded;
}
更新click事件以调用此事件处理程序并传递当前项值。还要更新[ngClass]以引用当前项对象实例上的isExpanded属性
[ngClass]="{'fa-angle-down':item.isExpanded, 'fa-angle-right':!item.isExpanded'}"
您的布尔值isExpanded
用于每个项目,因此如果项目将值更改为true
,则所有项目状态都将更改。您必须创建一个Map来存储每个项目状态,并使用它来确定节点是否已扩展。
我认为您可以使用item.reference
作为地图中的键来识别每个项目。
像这样的东西:
零件
import {Component, OnInit} from '@angular/core';
import {BlogService} from '../../../../services/blog.service';
@Component({
selector: 'app-sidenav',
templateUrl: './sidenav.component.html',
styleUrls: ['./sidenav.component.css'],
})
export class SidenavComponent implements OnInit {
files: [];
selectedFile: string;
selectedPath: string;
isExpanded = false;
public itemsState = new Map<string, boolean>();
constructor(private blogService: BlogService) {
}
ngOnInit() {
this.blogService
.getTreeNodes()
.subscribe((files: []) => {
console.log(files);
this.files = files;
this.files.forEach(item => {
// init all items to not expanded
this.itemsState.set(item.reference, false);
}
});
}
nodeSelectEvent(event) {
this.blogService.selectedNode.next(event.target.innerText);
}
}
HTML:
<div class="container sidenav-tree">
<ng-template #recursiveList let-files>
<div *ngFor="let item of files">
<div class="row node-item">
<i
data-toggle="collapse"
attr.data-target="#{{item.reference}}"
class="fa"
[ngClass]="{'fa-angle-down': itemsState.get(item.reference), 'fa-angle-right': !itemsState.get(item.reference)}"
*ngIf="!(item.children.length===0)"
(click)="isExpanded=!isExpanded"></i>
{{item.name}}
</div>
<div id="{{item.reference}}" class="container collapse" *ngIf="!(item.children.length===0)">
<ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: item.children }"></ng-container>
</div>
</div>
</ng-template>
<ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: files }"></ng-container>
</div>
代码未经过测试,只是为了解释原理