I have two components in Angular like this
@Component({
selector: 'content-com',
template: '<ng-content></ng-content>'
})
class ContentComponent {
// Select all the elements with .grouped css class
@ContentChildren('.grouped') grouped;
}
@Component({
selector: 'main-com',
template: `<content-com>
<div class="grouped"></div>
<div class="grouped"></div>
</content-com>`
})
class MainComponent {
}
Is it possible to select all the Content Children using a css selector (in my case class selector) ? If not, what is the best approach to do it ?
ContentChild & ContentChildren The concept of a content child is similar to that of a view child but the content children of the given component are the child elements that are projected into the component from the host component. In our example application we are projecting one joke in from the host AppComponent .
ViewChild is used to select an element from component's template while ContentChild is used to select projected content.
ViewChild and ContentChild are two very important features of Angular. It is used to access Child Component in the Parent Component. Any directive, component, and element which is part of component template is accessed as ViewChild.
You can do it easier, without creating directive. What you have to know is that the selector for ContentChildren has to be variable name. So:
@Component({
selector: 'content-com',
template: '<ng-content></ng-content>'
})
class ContentComponent {
@ContentChildren('grouped') grouped: QueryList<ElementRef>;
}
@Component({
selector: 'main-com',
template: `<content-com>
<div class="grouped" #grouped></div>
<div class="grouped" #grouped></div>
</content-com>`
})
class MainComponent {
}
You can do this by creating a directive. Let's call it Class
with selector [class]
, string Input bound to 'class' and hostbinding on the input variable also bound to 'class'
.
Then do @ContentChildren(Class, {descendants: true, read: ElementRef})
and filter that QueryList
for the specific classes you are interested in.
Here is the revised snippet:
Also See Plunker working here
// Remember to declare this in Module
@Directive({selector: '[class]'})
class Class {
@HostBinding('class') @Input('class') className: string = '';
}
@Component({
selector: 'content-com',
template: '<ng-content></ng-content>'
})
class ContentComponent implements AfterContentInit {
// Select all the elements with .grouped css class
@ContentChildren(Class, {descendants: true, read: ElementRef}) classes: QueryList<ElementRef>; // <--- Note This change
get grouped() {
if ( this.classes && this.classes.length ) {
return this
.classes
.map((elRef:ElementRef):Element => elRef.nativeElement)
.filter( (element: Element) => element.className == "grouped" );
}
return [];
}
ngAfterContentInit(){
console.log( this.grouped ); // <-- expect (2) [div.grouped, div.grouped]
}
}
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