26

Let's say I have a component like this in Angular 2.

@Component ({
   directives: [Timeline, VideoPlayer],
   template: `<div>
    <span id="myId"></span>
    <videoplayer [mode]="mode"></videoplayer>
    <timeline [mode]="mode"></timeline>
  </div>`,
})
export class VideoEditor {
}

How can I get a reference to an element from a template? For instance, how do I get a reference to a <span>?

I found two approaches so far:

1) Get a reference using ElementRef

export class VideoEditor {    
  constructor (private el: ElementRef) {
    el.nativeElement.getElementsBy.....;
  }
}

2) Using ViewChild

export class VideoEditor {  
  @ViewChild(Timeline) timeline: Timeline;  
  ngAfterViewInit () {
    this.timeline;
  }
}

3) Using local template variable


1) What I don't like about a first approach is that I need to do getElementsBy...-like function.

2) Regarding a second one, I don't know how to get an access to a HTML element, I can only get access to another sub-component. And what if I have more subcomponents of a same type?

3) Local template variable only works within a templates, am I right?

What is the best way to get a reference to a template in Angular 2? I'd like to have something like React has https://facebook.github.io/react/docs/more-about-refs.html#the-ref-string-attribute

<input ref="myInput" />

var input = this.refs.myInput;
var inputValue = input.value;
var inputRect = input.getBoundingClientRect();
vikram raj
  • 37
  • 8
Jan Vorcak
  • 19,261
  • 14
  • 54
  • 90

1 Answers1

38

You can use @ViewChild('varName') with a template variable (<tag #varName>) to get a specific element when you have more than one of the same type. You should try to avoid direct access anyway, use bindings instead if possible.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • 1
    Thanks for an answer, could you please elaborate a bit more on how to do things using bindings? What do you mean by that? – Jan Vorcak Jan 06 '16 at 15:20
  • This depends on what you actually want to do with the reference to the tag. With bindings I mean ``. – Günter Zöchbauer Jan 06 '16 at 15:22
  • Let's say I want to focus ``. The best way is to do `@ViewChild('keywordInput') keywordInput;` and then`this.keywordInput.nativeElement.focus();` am I right? Sorry this is a bit out of scope of my question. – Jan Vorcak Jan 06 '16 at 15:27
  • I think this only works if the referenced element is a native element (no Angular component/directive. You could build a reusable directive for that similar to the one shown in http://stackoverflow.com/questions/34502768/why-angular2-template-local-variables-are-not-usable-in-templates-when-using-ng/34503163#34503163 – Günter Zöchbauer Jan 06 '16 at 15:30
  • I used the @ViewChild('variableName') within the *ngIf and it alway returns undefined. How to solve this problem? – AustinTX Jul 28 '16 at 19:40
  • Please create a new question with more code that demonstrates what you're trying to accomplish. – Günter Zöchbauer Jul 28 '16 at 19:49
  • 3
    How do these "refs" work in angular2 (`#varName`, in this example)? Are they an angular2-specific construct? Are they a shortcut for adding an id? Does it disappear when the component gets compiled to stock HTML? I can't seem to find any official documentation on this. – matmo Sep 16 '16 at 00:05
  • 3
    Its called template variable. This is never added to the DOM but only used by Angular2. It allows you to reference the DOM element easily from binding expressions in the template and `ViewChild` and `ContentChild` in the compinents class. I don't know where in the docs it's explained more in-depht. – Günter Zöchbauer Sep 16 '16 at 03:06
  • If anyone does know where the doc for template variables is, please comment. AFAIK the variable can be an id or a class. Can we also just use a tag? – jon_two Feb 13 '17 at 14:58
  • 1
    No, either the name of the template variable or the type of the component or directive. – Günter Zöchbauer Feb 13 '17 at 15:00
  • 4
    https://angular.io/docs/ts/latest/guide/template-syntax.html#!#ref-vars – Günter Zöchbauer Feb 13 '17 at 15:01
  • I get it now - I was thinking of XPaths so thought the # meant id. Thanks. – jon_two Feb 13 '17 at 15:18
  • 1
    Updated URL for @GünterZöchbauer's link: https://angular.io/guide/template-reference-variables – Sander Aug 20 '20 at 20:45