Ayman
Ayman

Reputation: 1463

ContentChildren class selector

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 ?

Upvotes: 14

Views: 17998

Answers (2)

Somo  S.
Somo S.

Reputation: 4185

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]    

  }
}

Upvotes: 17

wawka
wawka

Reputation: 5154

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 {
}

Upvotes: 14

Related Questions