The Magic of Template Reference Variables


This series of blog posts which I have converted from Youtube videos. I personally have really enjoyed these videos so in order to textually document them, these are essentially some screenshots and rough notes organised. 

This particular post is based on the Alain Chautard NGConf 2018 talk on Template Reference. It can be found on the link below:

What are template reference variables?

 Template reference variables in Angular are a way to get a reference to an HTML element. It is usually called abstract syntax.

<input #phone placeholder=”Phone number”>

The tiny hashtag is added with the element in order to get a reference to it.

Here is how these reference can be used. If the input here is applied to, it will give a reference to an HTML so an access is gained to any property like IDS, classes, value or anything else.

<input #phone placeholder=”Phone number”>
<button (click)=”callPhone(phone.value)”>

In this example, value of the input is received and it is passed to the component whenever a button is clicked, because of this, any sort of data binding or ng model is not required in the component. Everything happens in the template.

Does this also work with component?

When a hashtag syntax is applied on a component, instead of a reference to the HTML element, a reference to the actual component instance is received, which means any property or method of that component outside of the template of that component can be accessed.

<app-hello #helloComp></app-hello>
{ {} }

Assuming that this component was a pop-up window, there could be a button which would just trigger the pop-up to show up outside of that template so that is a very good use case for it.

This also works with private or protected members in GT mode. In AoT (Application Object Templates), some issues will arrive.

Does this work with directives?


When this hashtag syntax is used with a directive, the name of the directive which is required to get a reference, will be passed. It is a very common use case.

The reference from ngForm directive is received, so that the validation state of the form, can be displayed.

<form #form=”ngForm”>
Form is valid: { {form.valid} }
Form is dirty: { {form.dirty} }

The things with this syntax is that, where the ngForm directive is actually applied to the form? Because there is no ngForm attribute on the form. How does this work?

To find the answer, go to the Angular website. Dive in to the documentation.

This feature (highlighted) where, with just one click, it can get to the source code of any class of this framework.

The answer is in the source

@Directive ( {
‘form: not ( [ngNoForm]) : not( [formGroup] )
exportAs: ‘ngForm’ ,
} )

Class NgForm extends ControlContainer implements

Form, AfterViewInit {

When the source code of ngForm directive is accessed, it can be observed that it applies to any form by default. This is because the selector of the directive is designed that way- it would applied to any form which does not have the ngNoForm nor the form group attribute.

This is how it works and this is why ngForm gets applied to any form by default.

Another interesting thing to observe here, is the exportAs property of the decorator. This exports the directive with a public name. Whenever a reference to that directive is required, the public name for it is ngForm.

We can also use those references with @ViewChild

The template reference variables can also be retrieved from the components all directive using the @ViewChild decorator.

If this hashtag syntax is applied in the template, a reference can be received to that variable in the typescript code using @ViewChild and then the name of the reference variable can be passed in here. This give access to those properties in the typescript code as well.

A few takeaways

Use template variables, which is very easy. It brings a lot of interesting features to the table and just like many things in Angular whereas always interesting lesser known use cases to all of these features.