10

Is there a way to retrieve ViewChildren or ContentChildren by element class?

This will work, either by id or component but not for the class based queries, namely classedViewItems and classedContentItems

@Component({
    selector: 'my-container',
    template '<div><ng-content><ng-content></div>'
})
export class MyContainer {
    @ViewChildren('item') viewItems: QueryList;
    @ContentChildren(MyItem) contentItems: QueryList;
    @ViewChildren('.fine-me') classedViewItems: QueryList; // <-- need this to work
    @ContentChildren('.find-me') classedContentItems: QueryList; // <-- or this
}

for the following:

<my-container>
    <my-item class="find-me" #item *ngFor="let item; of items"></my-item>
</my-container>

I need to get the query list by the element class without decorating it.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
Meir
  • 14,081
  • 4
  • 39
  • 47

2 Answers2

10

@ViewChild(), @ViewChildren(), @ContentChild(), @ContentChildren() only support the name of a template variable (or a comma separated list of names) or the types of components or directives as selectors as it is also mentioned in angular documentation.

There is no way to use other selectors. What you can do is to filter QueryList afterwards to only get the elements with a specific class but that doesn't free you from adding a template variable to each of them.

See also How can I select an element in a component template?

cuSK
  • 809
  • 11
  • 26
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Thx. So does that mean I need to add the variable, have a query list that includes all matched elements (even ones without the class) and then filter them? Does this mean I can't have a generic QueryList, one that gets the selection parameter as an input to the component? – Meir Oct 25 '16 at 07:39
  • 1
    Yes, adding the variable to all and later filter. If they aren't all of the same type you can't use the components type as generic type parameter for `QueryList`. – Günter Zöchbauer Oct 25 '16 at 07:43
7

It's an old question, but thanks to this link about carousel by Netanet Basal are a work around about the question.

If we write a simple directive, that has as selector a className -in the e.g. class "myClass", -you can add in the same .ts that your component, but don't forget declare in your module-

@Directive({
  selector: '.myClass'
})
export class MyClassElement {
}

Make possible has some like

@ViewChildren(MyClassElement , { read: ElementRef }) 
              private itemsElements : QueryList<ElementRef>;

In an .html

<div class="myClass">one</div>
<div class="myClass">two</div>
<div class="myClass">three</div>
Eliseo
  • 50,109
  • 4
  • 29
  • 67
  • 2
    This is an excellent answer, however didn't work for my case. from medium.com "One caveat with the class selector is that you cannot target class names that are dynamically inserted into the DOM using an expression binding either via a class binding or NgClass attribute directive." – javapedia.net Apr 24 '20 at 00:34