Я адаптировал код из дерева с динамическими c данными из: https://material.angular.io/components/tree/examples.
Это работало с загрузкой данных, но когда я закрываю родительский узел, не закрывая дочерние узлы, он не работает должным образом.
![enter image description here](https://i.stack.imgur.com/oPQ8l.png)
![enter image description here](https://i.stack.imgur.com/raQdo.png)
Я не знаю, что я делаю неправильно. В примере из документов он закрывает каждый уровень от конца до начала индивидуально. Но мой нет.
Это мой код:
import { Component, OnInit, Injectable } from '@angular/core';
import { FlatTreeControl } from '@angular/cdk/tree';
import { CollectionViewer, SelectionChange } from '@angular/cdk/collections';
import { BehaviorSubject, Observable, merge } from 'rxjs';
import { CatalogoBean, FilterBean } from '../../../common/rest/services/Beans';
import { map } from 'rxjs/operators';
import { ClasificacionControllerNg } from '../../../common/rest/services/ClasificacionControllerNg';
import { MatTreeFlatDataSource } from '@angular/material/tree';
export class FlatNode {
constructor(public catalogo: CatalogoBean,
public level: number = 1, public expandable: boolean = catalogo.hijos,
public isLoading?: boolean) { }
}
@Injectable({ providedIn: 'root' })
export class DynamicDataBase {
constructor(private clasificacionController: ClasificacionControllerNg) {
}
initialData(): Observable<any> {
const filterBean = {
inicio: 0,
maximo: 0,
direccion: '',
sort: undefined,
id: 0,
} as FilterBean;
return this.clasificacionController.listCatalogo(filterBean);
}
getChildren(node: CatalogoBean): Observable<any> {
const filterBean = {
inicio: 0,
maximo: 0,
direccion: '',
sort: undefined,
id: node.idcatalogo,
} as FilterBean;
return this.clasificacionController.listCatalogo(filterBean);
}
isExpandable(node: CatalogoBean): boolean {
return node.hijos;
}
}
export class DynamicDataSource {
dataChange: BehaviorSubject<FlatNode[]> = new BehaviorSubject<FlatNode[]>([]);
get data(): FlatNode[] {
return this.dataChange.value;
}
set data(value: FlatNode[]) {
this.treeControl.dataNodes = value;
this.dataChange.next(value);
}
constructor(private treeControl: FlatTreeControl<FlatNode>,
private database: DynamicDataBase) {
}
disconnect(collectionViewer: CollectionViewer): void {
}
connect(collectionViewer: CollectionViewer): Observable<FlatNode[]> {
this.treeControl.expansionModel.changed.subscribe(change => {
if ((change as SelectionChange<FlatNode>).added ||
(change as SelectionChange<FlatNode>).removed) {
this.handleTreeControl(change as SelectionChange<FlatNode>);
}
});
return merge(collectionViewer.viewChange, this.dataChange).pipe(map((node) => this.data));
}
handleTreeControl(change: SelectionChange<FlatNode>) {
if (change.added) {
change.added.forEach(node => this.toggleNode(node, true));
}
if (change.removed) {
change.removed.reverse().forEach((node) => this.toggleNode(node, false));
}
}
toggleNode(node: FlatNode, expand: boolean) {
const index = this.data.indexOf(node);
let children: Array<CatalogoBean>;
if (!node.catalogo.hijos || index < 0) { // If no children, or cannot find the node, no op
return;
} else {
this.database.getChildren(node.catalogo).subscribe((catalogos: Array<CatalogoBean>) => {
children = catalogos.filter(catalogo => catalogo.idcatalogo !== -1);
if (expand) {
node.isLoading = true;
const nodes = children.map(catalogo =>
new FlatNode(catalogo, node.level + 1, this.database.isExpandable(catalogo), false));
this.data.splice(index + 1, 0, ...nodes);
// notify the change
this.dataChange.next(this.data);
node.isLoading = false;
} else { // CERRADO
this.data.splice(index + 1, children.length);
this.dataChange.next(this.data);
}
});
}
}
}
@Component({
selector: 'app-tree-example',
templateUrl: './tree-example.component.html',
styleUrls: ['./tree-example.component.css'],
})
export class TreeExampleComponent {
treeControl: FlatTreeControl<FlatNode>;
dataSource: DynamicDataSource;
getLevel = (node: FlatNode) => node.level;
isExpandable = (node: FlatNode) => node.expandable;
hasChild = (_: number, _nodeData: FlatNode) => _nodeData.expandable;
constructor(private clasificacionController: ClasificacionControllerNg, database: DynamicDataBase) {
this.treeControl = new FlatTreeControl<FlatNode>(this.getLevel, this.isExpandable);
this.dataSource = new DynamicDataSource(this.treeControl, database);
database.initialData().subscribe((catalogos: Array<CatalogoBean>) => {
catalogos = catalogos.filter(catalogo => catalogo.idcatalogo !== -1);
this.dataSource.data = catalogos.map(node => new FlatNode(node, 0, node.hijos, false));
});
}
}
Любая помощь приветствуется.