Первое, что он знает, как сделать это, используя .css. Я нахожу эту красоту Минималистичный вид дерева в чистом CSS
Что ж, с этой идеей мы можем использовать Angular для генерации "рекурсивного компонента". но сначала мы должны принять во внимание, что нам нужно использовать «селектор атрибута», чтобы не генерировать тег компонента. Не волнуйтесь, он используется только в качестве селектора, например,
selector: '[recursive]'
Итак, вместо того, чтобы написать что-то вроде
<recursive></recursive>
мы можем использовать что-то вроде
<ul recursive></ul>
Ну, компонент похож на
<li *ngFor="let item of children">
{{item.label}}
<ul recursive *ngIf="item.children"
[children]="item.children"
[parent]="self"
[level]="level!=undefined?level+1:0">
</ul>
</li>
@Component({
selector: '[recursive]', //<--the the "selector"
templateUrl:'./hello.component.html'
})
export class HelloComponent {
@Input() level: number;
@Input() label: string;
@Input() children: any;
@Input() parent: any;
self=this;
}
Ну, я добавляю свойства "level" и "parent", которые я не использую в коде, но это может быть интересно, если наш компонент создает "some-more", которое показывает дерево.
А наш app.component.html похож на
<ul class="tree" recursive [children]="data"></ul>
Будь осторожен . Мне нужно использовать ViewEncapsulation.None в app.component для транспортировки .css
Смотрите, что мы даем [детям] собственные данные
где, например
data = [{label: "Parent1", children: [
{ label: "Parent 1's only child" }
]},
{label:"Parent2"},
{label:"Parent3", children: [
{ label: "1st Child of 3" ,children:[
{label:"1st grandchild"},
{label:"2nd grandchild"}
]},
{ label: "2nd Child of 3" },
{ label: "3rd Child of 3" }
]
},
{
label: "Parent 4", children: [
{ label: "Parent 4's only child" }
]}]
Вы можете увидеть в этот стек
Обновлено Если мы хотим добавить емкость открытия / закрытия, легко добавить диапазон и использовать [ngClass] для трех случаев: doc, open и close, поэтому наш рекурсив. HTML становится
<li *ngFor="let item of children">
<span [ngClass]="!item.children?
'doc':item.isOpen?'open':'close'"
(click)="item.isOpen=!item.isOpen"></span>
{{item.label}}
<ul recursive *ngIf="item.children && item.isOpen"
[children]="item.children"
[parent]="self"
[level]="level!=undefined?level+1:0">
</ul>
</li>
Я использовал .css как
.doc,.open,.close
{
display:inline-block;
width:1rem;
height:1rem;
background-size: 1rem 1rem;
}
.doc
{
background-image:url('...');
}
.open
{
background-image:url('...');
}
.close
{
background-image:url('...');
}
Обновленный стек
Обновлено 2 Мне не очень нравится использовать ViewEncapsulation.None, поэтому мы можем обойти это, и наш рекурсивный компонент становится похожим на
<ul class="tree" *ngIf="level==undefined">
<ng-container *ngTemplateOutlet="tree;context:{children:children}">
</ng-container>
</ul>
<ng-container *ngIf="level!=undefined">
<ng-container *ngTemplateOutlet="tree;context:{children:children}">
</ng-container>
</ng-container>
<ng-template #tree let-children="children">
<li *ngFor="let item of children">
<span [ngClass]="!item.children?'doc':item.isOpen?'open':'close'" (click)="item.isOpen=!item.isOpen"></span>{{item.label}}
<ul recursive *ngIf="item.children && item.isOpen"
[children]="item.children"
[parent]="self"
[level]="level!=undefined?level+1:0">
</ul>
</li>
</ng-template>
Это. Первое использование <ul class="tree">...</ul>
, другие не добавляют <ul>
И снова окончательный стек