Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ContentChildren class selector

Tags:

angular

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 ?

like image 347
Ayman Avatar asked May 01 '17 20:05

Ayman


People also ask

What is ContentChild and ContentChildren?

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 .

What is the difference between ViewChild () and ContentChild ()?

ViewChild is used to select an element from component's template while ContentChild is used to select projected content.

What is view and content in angular?

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.


2 Answers

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 {
}
like image 155
wawka Avatar answered Sep 20 '22 09:09

wawka


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]    

  }
}
like image 20
Somo S. Avatar answered Sep 19 '22 09:09

Somo S.