So I'm trying to display child components at specific locations in my Component.
I have the following:
@Component({
selector: 'app-item-list',
template: `
<p *ngFor="let item of items">
{{item.order}}
<!-- display content of child component here -->
</p>`
})
export class ItemListComponent implements OnInit, AfterContentInit {
//Get all child components of the type ItemComponent and store them.
@ContentChildren(ItemComponent, {descendants: true})
items?: QueryList<ItemComponent>;
constructor() { }
ngOnInit() {
}
ngAfterContentInit(): void {
}
}
@Component({
selector: 'app-item',
template: `
<p>
item works!
</p>
<ng-content></ng-content>
`
})
export class ItemComponent implements OnInit {
@Input() order?: string;
constructor() { }
ngOnInit() {
}
}
I tried to display it using <ng-content select="item">
but that didn't work.
With the following:
<app-item-list>
<app-item order="2">
test2
</app-item>
<app-item order="1">
test1
</app-item>
</app-item-list>
the expected output is
2
item works!
test2
1
item works!
test1
https://stackblitz.com/edit/angular-ivy-2aibgt
So, the answer to your question is pretty simple: The difference between @ViewChildren and @ContentChildren is that @ViewChildren look for elements in Shadow DOM while @ContentChildren look for them in Light DOM.
The ViewChild or ViewChildren decorators are used to Query and get the reference of the DOM element in the Component. ViewChild returns the first matching element and ViewChildren returns all the matching elements as a QueryList of items. We can use these references to manipulate element properties in the component.
The ContentChild & ContentChildren are decorators, which we use to Query and get the reference to the Projected Content in the DOM. Projected content is the content that this component receives from a parent component. The ContentChild & ContentChildren is very similar to the ViewChild & ViewChildren.
ViewChild is used to select an element from component's template while ContentChild is used to select projected content.
I can suggest you a solution that is used in Angular material library.
app-item
component in <ng-template>
tagitem.component.html
<ng-template> <----------------------------- wrapper
<p>
item works!
</p>
<ng-content></ng-content>
</ng-template>
TemplateRef
item.component.ts
@ViewChild(TemplateRef, {static: true}) template: TemplateRef<any>;
app-item-list
componentitem-list.component.html
<p *ngFor="let item of items">
{{item.order}}
<ng-template [ngTemplateOutlet]="item.template"></ng-template>
</p>
Forked Stackblitz
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With