How do I select a ContentChild of a native element in Angular 6?

Yulian picture Yulian · Aug 3, 2018 · Viewed 7.8k times · Source

I have a component that uses content projection.

<ng-content select="button">
</ng-content>

I want to do something like this in my component:

@ContentChild('button') button: ElementRef;

However, when I check this.button, it is undefined both in ngAfterViewInit and ngAfterContentInit.

How can I select my content child if it is a native element and not a custom component?

Answer

Cobus Kruger picture Cobus Kruger · Aug 3, 2018

The important thing to understand is that the selector you pass to @ContentChild is not a CSS selector, and you cannot find a content child based on its ID, class or element type. You can only search on the identifier name you gave it using the # operator.

So given a component called my-comp and the following usage:

<my-comp><button #buttonName>Click me</button></my_comp>

You can find it using:

@ContentChild('buttonName') button: ElementRef;

Edit

As noted in the OP's comment on ckTag's answer (he beat me to it by a minute), that does mean the calling code will need to know you expect the content to be tagged with a specific name.

If your component does actually need to know detail of its content children, the better answer is actually to provide the directive type to @ContentChild:

@ContentChild(MyButtonComponent, { read: ElementRef })
button: ElementRef;

This is also better, because you can now realistically expect to know the type of content; the calling code can stick #button on a div if it feels like it, after all.

That does mean saying goodbye to using a regular HTML button element, but comes with other benefits. You could, for example, provide a message to guide your calling code, like this:

<ng-content></ng-content>
<div *ngIf="button">Error: Please provide a MyButtonComponent</div>