In an Angular project, I am attempting to display a private group's data from GitLab (utilizing a public one for testing purposes). To achieve this, I have implemented the NestedTreeView component. While the parent nodes are displaying correctly, I am encountering difficulties in rendering their children. The structure of the fetched data from GitLab's API aligns with what the TreeView component expects. Here is the relevant code snippet:
data.ts
export interface Data {
name: string;
id?: string;
children?: Data[]
}
data.service.ts
@Injectable({
providedIn: 'root'
})
export class DataService {
constructor(public http: HttpClient) { }
getEndpoint(id: string): string
{
return `https://gitlab.com/api/v4/groups/${id}/subgroups`
}
getRoot(): Observable<Data[]>{
return this.http.get<Data[]>(this.getEndpoint("9970")).pipe(
map((res: any) =>
res.map((data: Data) =>
{
return {
name: data.name,
id: data.id,
}
})
)
)
}
getNodes(subid: string): Observable<Data[]>
{
return this.http.get<Data[]>(this.getEndpoint(subid)).pipe(
map((res: any) =>
res.map((data: Data) =>
{
return {
name: data.name,
id: data.id,
}
})
)
)
}
}
sidebar.component.ts
@Injectable({
providedIn: 'root' })
@Component({
selector: 'app-sidebar',
templateUrl: './sidebar.component.html',
styleUrls: ['./sidebar.component.scss']
})
export class AppSidebarComponent implements OnDestroy,OnInit {
mobileQuery: MediaQueryList;
private _mobileQueryListener: () => void;
result: Data[] = [];
treeControl = new NestedTreeControl<Data>(node => node.children);
dataSource = new MatTreeNestedDataSource<Data>();
constructor(
changeDetectorRef: ChangeDetectorRef,
media: MediaMatcher,
public menuItems: MenuItems,
public http: HttpClient,
public dataService: DataService
) {
this.mobileQuery = media.matchMedia('(min-width: 768px)');
this._mobileQueryListener = () => changeDetectorRef.detectChanges();
this.mobileQuery.addListener(this._mobileQueryListener);
this.getRoots();
}
ngOnInit(): void {
}
getRoots()
{
this.dataService.getRoot().subscribe(response => {
this.result = response
this.result.forEach(directory => {
let nodeList: Data[]= []
this.dataService.getNodes(directory.id!).subscribe(response => {
nodeList = <Data[]> response
if(nodeList.length>0)
directory.children = nodeList;
nodeList = [];
})
});
console.log(this.result);
this.dataSource.data = this.result;
})
}
ngOnDestroy(): void {
this.mobileQuery.removeListener(this._mobileQueryListener);
}
hasChild = (_: number, node: Data) => !!node.children && node.children.length>0;
}
sidebar.component.html
<mat-tree [dataSource]="dataSource" [treeControl]="treeControl" class="example-tree">
<mat-tree-node *matTreeNodeDef="let node" matTreeNodeToggle>
{{node.name}}
</mat-tree-node>
<mat-nested-tree-node *matTreeNodeDef="let node; when: hasChild">
<div class="mat-tree-node">
<button mat-icon-button matTreeNodeToggle
[attr.aria-label]="'Toggle ' + node.name">
<mat-icon class="mat-icon-rtl-mirror">
{{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
</mat-icon>
</button>
{{node.name}}
</div>
<div [class.example-tree-invisible]="!treeControl.isExpanded(node)"
role="group">
<ng-container matTreeNodeOutlet></ng-container>
</div>
</mat-nested-tree-node>
</mat-tree>