Использовать компонент в себе рекурсивно для создания дерева
Знаете ли вы, что можно использовать компонент сам по себе? Если да, где читать об этом?
У меня следующая ситуация:
есть список основных элементов, каждый основной элемент имеет subItem (то же самое похоже на mainItem), каждый subItem может иметь свой собственный subItem и т.д.
Так что лучше использовать вложенность, но как?
Ответы
Ответ 1
Обновление
forwardRef()
больше не требуется, потому что directives
был перенесен на NgModule.declarations
, и поэтому рекурсивные компоненты не должны быть зарегистрированы сами по себе как directives
.
Angular 4.x.x Пример плунжера
оригинальный
Это поддерживается. Вам просто нужно добавить компонент в directives: []
в его декоратор @Component()
. Поскольку декоратор приходит перед классом, и классы не могут быть указаны, прежде чем они будут объявлены forwardRef()
.
import {Component, forwardRef, Input} from '@angular/core'
@Component({
selector: 'tree-node',
template: `
<div>{{node.name}}</div>
<ul>
<li *ngFor="let node of node.children">
<tree-node [node]="node"></tree-node>
</li>
</ul>
`
})
export class TreeNode {
@Input() node;
}
@Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
<tree-node [node]="node"></tree-node>
</div>
`,
directives: [TreeNode]
})
export class App {
constructor() {
this.name = 'Angular2 (Release Candidate!)'
}
node = {name: 'root', children: [
{name: 'a', children: []},
{name: 'b', children: []},
{name: 'c', children: [
{name: 'd', children: []},
{name: 'e', children: []},
{name: 'f', children: []},
]},
]};
}
Angular 2.0.0-beta.x Пример плунжера
См. также Вставить родительский компонент того же типа, что и дочерний компонент
Ответ 2
Angular 4 пример рекурсивных компонентов: https://plnkr.co/edit/IrW82ye4NKK8cYEPxsFc?p=preview
Выдержка из связанного примера:
//our root app component
import {Component, NgModule, VERSION, Input} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
@Component({
selector: 'tree-node',
template: '
<div>{{node.name}}</div>
<ul>
<li *ngFor="let node of node.children">
<tree-node [node]="node"></tree-node>
</li>
</ul>
'
})
export class TreeNode {
@Input() node;
}
@Component({
selector: 'my-app',
providers: [],
template: '
<div>
<h2>Hello {{name}}</h2>
<tree-node [node]="node"></tree-node>
</div>
'
})
export class App {
constructor() {
this.name = 'Angular2 (Release Candidate!)'
}
node = {name: 'root', children: [
{name: 'a', children: []},
{name: 'b', children: []},
{name: 'c', children: [
{name: 'd', children: []},
{name: 'e', children: []},
{name: 'f', children: []},
]},
]};
}
@NgModule({
imports: [ BrowserModule ],
declarations: [ App, TreeNode ],
bootstrap: [ App ]
})
export class AppModule {}
Этот ответ является вики-сообществом, потому что пример ссылки был скопирован из ответа Гюнтера Цохбауэра. Я включил код в тело вопроса, чтобы избежать гниения ссылок.
Ответ 3
Работая с Angular 7, я нашел другие решения для описания ссылки здесь, которые кажутся близкими к ответу Шеннона (я даю эту ссылку, потому что я нашел ее полезной для меня, как для начинающего)
Ответ 4
Использование ng-template
является лучшим решением для решения рекурсивных проблем DOM.
@Component({
selector: 'tree-node',
template: '
<ng-container *ngTemplateOutlet="tree;context:{node:node}">
</ng-container>
<ng-template #tree let-node="node">
<div>{{node.name}}</div>
<ul *ngIf="node.children && node.children.length > 0">
<ng-container *ngFor="let child of node.children">
<li>
<ng-container *ngTemplateOutlet="tree;context:{node:child}">
</ng-container>
</li>
</ng-container>
</ul>
</ng-template>
'
})
export class TreeNode {
@Input() node;
}
Нет необходимости добавлять компонент в directives: []
в его @Component()
.
@Component({
selector: 'my-app',
template: '
<div>
<h2>Hello {{name}}</h2>
<tree-node [node]="node"></tree-node>
</div>
'
})
export class App {
node = {
name: 'root', children: [
{ name: 'a', children: [] },
{
name: 'b', children: [
{ name: 'b-1', children: [] },
{
name: 'b-2', children: [
{ name: 'b-2-1', children: [] },
{ name: 'b-2-2', children: [] },
{ name: 'b-2-3', children: [] }
]
}
]
},
{
name: 'c', children: [
{ name: 'c-1', children: [] },
{ name: 'c-2', children: [] }
]
},
]
};
}
Выход:
HTML:
<app-tree-node>
<div>root</div>
<ul>
<li>
<div>a</div>
</li>
<li>
<div>b</div>
<ul>
<li>
<div>b-1</div>
</li>
<li>
<div>b-2</div>
<ul>
<li>
<div>b-2-1</div>
</li>
<li>
<div>b-2-2</div>
</li>
<li>
<div>b-2-3</div>
</li>
</ul>
</li>
</ul>
</li>
<li>
<div>c</div>
<ul>
<li>
<div>c-1</div>
</li>
<li>
<div>c-2</div>
</li>
</ul>
</li>
</ul>
</app-tree-node>