2

I am currently working on a directive which simply manipulates the dom elements.

I wanted to access to template variables of the element which is the host of the directive, but I was unable to do that, because the result is always undefined.

directive:

@Directive({
    selector: '[sample-directive]'
})
export class SampleDirective implements AfterViewInit {
    @ViewChild('queryMe') queryMe: ElementRef;

    ngAfterViewInit(): void {
        console.log(this.queryMe);    
    }
}

sampleComponent.template.html:

<div #queryMe></div>

usage:

<sample-component [sample-directive]></sample-component>

Is it possible to use template variables like that?

2 Answers 2

3

Send the template variables over to your directive : stackblitz

@Input('appQuery') appQuery: HTMLElement;
<div [appQuery]="queryMe">
  <div #queryMe></div>
</div>

EDIT

Second solution : provide custom attributes to your query-able elements. Since template variables are just references to HTML elements, you will get pretty much the same result (except for one more attribute in your tag).

Stackblitz

get element() { return this.el.nativeElement; }
ngAfterViewInit() {
  console.log(this.element.querySelector('[queryMe]'));
}
<div appQuery>
  <div queryMe></div>
</div>
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, but I was curious about the behavior of template variables and I don't want to pollute my directive inputs with all of the elements I want to use(5 or 6).
@BalázsTakács I made an edit to my answer, in case you want to see it
2

Angular Directives don't have a template. That's what differentiates them from Angular Components which does have templates.

Since directives have no templates, you can't get things like ViewChild or ContentChild on them. Also for the same reason, you'll not have implementations to AfterContentInit, AfterContentChecked, AfterViewInit, and AfterViewChecked interfaces.

So if you only want the HTMLElement from your host's template, give the div a class and access it from the directive using this:

import { ElementRef, Directive } from '@angular/core'

@Directive({
    selector: '[sample-directive]'
})
export class SampleDirective {

    constructor(private el: ElementRef) {}

    ngOnInit() {
      let elYoureLookingFor = this.el.nativeElement.querySelector('.class-on-div');
    }

}

Then, in your sampleComponent.template.html:

<div class="class-on-div"></div>

4 Comments

I am doing it now. But I would like to try it with template variables. As it turned out I don't know how these work so I have room to grow in knowledge.
@BalázsTakács You cannot use @ViewChild('queryMe') queryMe: ElementRef; inside directive class SampleDirective, because it is not a child element of your directive SampleDirective
One more question. Why does it work with ngAfterViewInit function if directive does not have this lifecycle hook?
@Amit Chigadani what is the border for child elements here? Because I can access to SampleComponent wtih viewChild.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.