9

I've been googling around, and am still a bit new to angular 5/6, but I'm trying to see if something is possible.


Problem

Say I have a template:

<ng-template #rt let-r="result" let-t="term">
  <ngb-highlight [result]="r.typeAheadDisplayName" [term]="t" ></ngb-highlight>
  <span *ngIf="r.primaryName ">(alias for {{ r.primaryName }}) </span>{{ r.metaData }}
</ng-template>

Within this template a button will generate that can be used as a means of chosing an option. However, for a given reason I need to be able to target :first-child of the array of buttons.

I know that I can select the element/template doing:

@ViewChild('rt') rt : TemplateRef<any>;

but, can I actually do a function similar to jQuery's .find or even the same in AngularJS, to target the elements that would be found inside of this template. I've been googling and can't see to find an answer.

Mark Hill
  • 1,769
  • 2
  • 18
  • 33

1 Answers1

7

nativeElement is what you're looking for. It will give you the native DOM node, and from that you can use methods like querySelector to query child nodes.

@Component()
export class MyComponent implements OnInit {
    @ViewChild('rt') rt : ElementRef;

    ngOnInit() {
        const childNode = this.rt.nativeElement.querySelector('.child-class');
    }
}

Update:

For using ng-template, you can use ContentChild and TemplateRef together. TemplateRef still has an embedded ElementRef within it, so you will still be able to access the nativeElement property and do whatever querying you want.

<ng-template [ngTemplateOutlet]="rt"></ng-template>

@Component({selector: 'my-component'})
export class MyComponent implements OnInit {
    @ContentChild('rt') rt: TemplateRef<any>;

    ngOnInit() {
        const childNode = this.rt.elementRef.nativeElement.querySelector('.foo');
    }
}

Now you can use that component like so:

<my-component>
    <ng-template #rt>
        <div class="foo">Hello world</div>
    </ng-template>
</my-component>
Lansana Camara
  • 9,497
  • 11
  • 47
  • 87
  • okay, so I'm going to revise my questions because I just realized that this is specifically for an ng-template. QuerySelector isn't a function on templateRef though – Mark Hill May 18 '18 at 18:31
  • Updated answer. Does that do the trick? By the way, my first solution will still work with a `TemplateRef`, just use `this.rf.elementRef.nativeElement` instead of `this.rt.nativeElement`. – Lansana Camara May 18 '18 at 18:47
  • 1
    yes it does, thank you very much. This was very informative. – Mark Hill May 18 '18 at 18:48
  • Also, take a look at [my question/answer here](https://stackoverflow.com/questions/46810145/angular-2-use-a-template-for-ng-content-to-use-inside-component-loop). Might be similar to something you are trying to do, or might be a good bookmark for later: – Lansana Camara May 18 '18 at 18:50
  • I suppose `querySelector` is a Javascript function. Is it safe to use Javascript functions directly in Angular code w.r.t. portability? I would like to avoid mixing Javascript code in Angular code. Do you know a way how to do this without using pure javascript (Renderer2, ViewChild)? – Manu Chadha Aug 08 '18 at 06:06
  • If you need server-side rendering, etc., then using `querySelector` directly is not good. You can use the `Renderer2` variant. Do a quick search online, but [here is an example you can follow](https://stackoverflow.com/questions/38944725/how-to-get-dom-element-in-angular-2#38944920). – Lansana Camara Aug 08 '18 at 13:45
  • 1
    For me, `this.rt.elementRef.nativeElement` just returns "comment", not the html element it embeds – DongBin Kim Feb 12 '19 at 07:43
  • Same as @DongBin Kim, it returns the comment, cant use queryselector either – Mauro Insacco May 17 '20 at 21:21
  • @MauroInsacco The Angular API may have changed over time, I'd have to take a look at this code again to give an updated answer. Please refer to the Angular API for the time being, maybe I'll find some time to do this later. – Lansana Camara May 19 '20 at 20:27