Can an angular2 directive access the template of a component it's applied to?


March 2019


424 time


Updated thanks to Gunter's answer and now that I better understand what I'm asking:

If I'm writing a custom directive and I plan to apply it to a component, what's the best way to have my directive query that component's template?

I'm writing an attribute directive, whose objective is simply to change the styling of the first custom button component it finds in its host. If the host itself is my custom button component, it shows up in my directive's ContentChildren query for some reason. And if the host instead contains my custom button component in its template, my directive can't find it.

Here's my directive:

import { Directive, AfterViewInit, AfterContentInit, ContentChildren, QueryList, ViewChild, ElementRef } from '@angular/core';
import { MyCustomButtonComponent } from './my-custom-button.component';

    selector: '[specialButton]'
export class SpecialButtonDirective implements AfterViewInit, AfterContentInit {

    hostElement: ElementRef;
    @ViewChild(MyCustomButtonComponent) myCustomButtonViewChild;
    @ContentChildren(MyCustomButtonComponent, {descendants: true}) myCustomButtonQueryList: QueryList<MyCustomButtonComponent>;

    constructor(el: ElementRef) {
        this.hostElement = el;

    ngOnInit() {
        //Should I query here? Via this.hostElement.nativeElement.querySelector(...) perhaps?

    ngAfterContentInit(): void {
        console.log('Value of myCustomButtonQueryList.first [' + this.myCustomButtonQueryList.first + ']');
    ngAfterViewInit(): void {
        console.log('Value of myCustomButtonViewChild [' + this.myCustomButtonViewChild + ']');

And then in my main component, which includes MyCustomButtonComponent and SpecialButtonDirective in its directives:

<my-custom-button specialButton>Host is Button</my-custom-button>
<!-- Value of myCustomButtonQueryList.first [[object Object]] -->
<!-- Value of myCustomButtonViewChild [undefined] -->

<!--The dropdown toggle button is a my-custom-button in my-custom-dropdown's template -->
<my-custom-dropdown specialButton>
        <li><div>Item 1</div></li>
        <li><div>Item 2</div></li>
<!-- Value of myCustomButtonQueryList.first [undefined] -->
<!-- Value of myCustomButtonViewChild [undefined] -->

I don't understand why the first example finds my custom button component, because I thought ContentChildren only searched within the ng-content tags, but it's picking up the host MyCustomButtonComponent.

And I don't understand why the second example doesn't work, because I thought that ViewChild was supposed to search my-custom-dropdown's template? And yet it's not finding the instance of MyCustomButtonComponent in there.

1 answers


A directive doesn't have a view, therefore @ViewChild() won't work. @ContentChildren() is supported though.