Reputation: 219
I created an array of objects:
folders = [
{
id: 1,
folderName: "Folder1",
files: ["File 1", "File 2"],
folder: [
{
folderName: "Subfolder of folder1",
folder: []
}
]
},
{
id: 2,
folderName: "Folder2",
files: ["File 1", "File 2"],
folder: []
}
]
and I want to display the information, also the information of the subfolder as a sublist under the folder name:
<ul *ngFor="let folder of folders">
<li> {{folder.id}} {{folder.folderName}}
<ul>
<li>{{folder.files}}</li>
</ul>
</li>
<ng-container *ngIf="!(folder.folder.length <= 0)">
<ul *ngFor="let folder2 of folder.folder">
<li>
{{folder2.id}} {{folder2.folderName}}
<ul>
<li>{{folder.files}}</li>
</ul>
</li>
</ul>
</ng-container>
</ul>
Now I wonder how I could display a folder with an arbitrary number of subfolders. In my approach I always have to add code if I want to go one more level down but that would be repetitive. Is there another way of solving this problem?
Upvotes: 0
Views: 1499
Reputation: 798
<ng-container *ngFor="let folder of folders">
<app-folder [folder]="folder" [indentationLevel]="0"></app-folder>
</ng-container>
<div class="folder-row" style="margin-left: {{indentationLevel * 32}}px" (click)="folder.isExpanded = !folder.isExpanded">
<ion-icon class="folder-row__icon" *ngIf="folder.type === folderType.group" [name]="folder.isExpanded ? 'folder-open' : 'folder'"></ion-icon>
<img class="folder-row__user-image" src="assets/mock-data/{{folder.userId}}.jpg" *ngIf="folder.type === folderType.user" alt="👤">
{{folder.title}}
</div>
<ng-container *ngIf="folder.isExpanded">
<ng-container *ngFor="let folder of folder.subFolders">
<app-folder [folder]="folder" [indentationLevel]="indentationLevel + 1"></app-folder>
</ng-container>
</ng-container>
style="margin-left: {{indentationLevel * 32}}px"
this creates inline styling based on class value
parent: base case:
[indentationLevel]="0"
folder: progress:
[indentationLevel]="indentationLevel + 1"
Upvotes: 0
Reputation: 2708
I like to use ng-template
for these kinds of things. You can define a re-usable template that in turn renders its self.
<ng-container *ngFor="let folder of folders">
<ul>
<ng-container [ngTemplateOutlet]="folderNode" [ngTemplateOutletContext]="{$implicit:folder}"></ng-container>
</ul>
</ng-container>
<ng-template #folderNode let-folder>
<li> {{folder.folderName}} </li>
<li *ngFor="let file of folder.files">{{file}}</li>
<ng-container *ngIf="folder.folder">
<ng-container *ngFor="let subFolder of folder.folder">
<ul>
<ng-container [ngTemplateOutlet]="folderNode" [ngTemplateOutletContext]="{$implicit:subFolder}">
</ng-container>
</ul>
</ng-container>
</ng-container>
</ng-template>
Upvotes: 1
Reputation: 813
You can use a recursive component.
First you can define a Folder interface :
interface Folder {
id: number;
folderName: string;
files: string[];
folders: Folder[];
}
Then use it to define your data properly :
const folder: Folder = {
id: 0,
folderName: "Folder0",
files: ["File 1", "File 2"],
folders: [
{
id: 1,
folderName: "Folder1",
files: ["File 1", "File 2"],
folders: [
{
id:3,
files: ["File 1"],
folderName: "Subfolder of folder1",
folders: []
}
]
},
{
id: 2,
folderName: "Folder2",
files: ["File 1", "File 2"],
folders: []
}
]
};
Then create a component to display any Folder object :
*.html
<h1>{{ folder.folderName }}</h1>
<ul>
<li *ngFor="let fileName of folder.files">
{{ fildeName }}
</li>
</ul>
<!-- Display subfolders -->
<display-folder *ngFor="let subFolder of folder.folders" [folder]="subFolder"></display-folder>
*.ts
@Component({
selector: 'display-folder',
...
})
export class DisplayFolder {
@Input() folder: Folder;
}
Upvotes: 2