228

I have been reading the Angular 1 to 2 quick reference in the Angular website, and one thing I didn't completely understand was the difference between these special characters. For example one that uses asterisks:

<tr *ngFor="#movie of movies">
   <td>{{movie.title}}</td>
</tr>

I understand here that the hash (#) symbol defines movie as a local template variable, but what does the asterisk before ngFor mean? And, is it necessary?

Next, are the examples that use brackets:

<a [routerLink]="['Movies']">Movies</a>

I somewhat understand that the brackets around routerLink bind it to that HTML attribute / Angular directive. Does this mean that they are a pointer for Angular to evaluate an expression? Like [id]="movieId" would be the equivalent of id="movie-{{movieId}}" in Angular 1?

Lastly, are parentheses:

<button (click)="toggleImage($event)">

Are these only used for DOM events and can we use other events like (load)="someFn()" or (mouseenter)="someFn()"?

I guess the real question is, do these symbols have a special meaning in Angular 2, and what is the easiest way to know when to use each one? Thanks!!

Roy
  • 7,811
  • 4
  • 24
  • 47
David Meza
  • 3,080
  • 3
  • 16
  • 18

3 Answers3

235

All details can be found here: https://angular.io/docs/ts/latest/guide/template-syntax.html

  • directiveName - is the short hand form for structural directives where the long form can only be applied to <template> tags. The short form implicitely wraps the element where it's applied in a <template>.

  • [prop]="value" is for object binding to properties (@Input() of an Angular component or directive or a property of a DOM element).
    There are special forms:

    • [class.className] binds to a css class to enable/disable it
    • [style.stylePropertyName] binds to a style property
    • [style.stylePropertyName.px] binds to a style property with a preset unit
    • [attr.attrName] binds a value to an attribute (visible in the DOM, while properties are not visible)
    • [role.roleName] binds to the ARIA role attribute (not yet available)
  • prop="{{value}}" binds a value to a property. The value is stringified (aka interpolation)

  • (event)="expr" binds an event handler to an @Output() or DOM event

  • #var or #var has different functions depending on the context

    • In an *ngFor="#x in y;#i=index" scope variables for the iteration are created
      (In beta.17 this is changed to *ngFor="let x in y; let i=index"`)
    • On a DOM element <div #mydiv> a reference to the element
    • On an Angular component a reference to the component
    • On an element that is an Angular component or has an Angular directive where exportAs:"ngForm" is defined, #myVar="ngForm" creates a reference to this component or directive.
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • 21
    Or `bind-` for `[]` and `on-` for `()` or ` – Günter Zöchbauer Mar 13 '16 at 07:13
  • @pradeep Jain I think you mean ref- prefix and not var- . https://angular.io/docs/ts/latest/guide/template-syntax.html#!#ref-vars – Swapnil Mhaske Mar 13 '17 at 07:31
  • @SwapnilMhaske that changed since then. `var` was replaced by `ref` and `let`. – Günter Zöchbauer Mar 13 '17 at 07:40
  • 11
    What does [(ngModel)] mean i.e. parenthesis within square brackets? – Uthman Aug 28 '17 at 21:21
  • 21
    Two-way binding (also called "banana in a box6). It's the combination (or short form of) of `[ngModel]="foo" (ngModelChange)="foo = $event"` where the first part updates the `ngModel` property (`@Input() ngModel;` of the `NgModel` directive`) when `foo` changes and the 2nd part updates `foo` when the `@Output() ngModelChange;` (of the `NgModel` directive) emits an event. `NgModel` is used to bind values to form elements and components. `[(bar)]` can be used for any `@Input() bar;` `@Output() barChange;` combination, also of your own components. – Günter Zöchbauer Aug 29 '17 at 03:08
  • I'd recommend to change your `[style.styleName]` to `[style.styleProperty]` or to `[style.background]` because Style Name is misleading here – Dmitry Gusarov May 01 '18 at 07:58
  • 5
    @GünterZöchbauer What is the difference between `[prop]="value"` and `prop="{{value}}"` anything else than syntax? Both of them can pass value to `@Input() value;` in component. – DiPix May 15 '18 at 10:08
  • 9
    @DiPix `[prop]="value"` can assign values of any type, `prop="{{value}}"` always stringifies `value` before assignment and is therefore useless to pass objects. – Günter Zöchbauer May 15 '18 at 10:18
  • Alright. So when I want to only display `value` then it doesn't matter which way I will use? – DiPix May 15 '18 at 10:31
  • 1
    @DiPix no, doesn't matter, because HTML can only render string anyway, but if you want to pass a value to an `@Input()` that is not of type `string`, then `{{value}}` won't work. Also some properties (in contrary to attributes) of native HTML elements are not of type string and can cause issues if set with `{{}}`. You're always safe with `[prop]="value"`, at least I don't know an example where this would cause issues and `prop={{value}}` would not. – Günter Zöchbauer May 15 '18 at 10:34
  • 2
    Thank you for explaining all. Pardon my straight forward speaking, "complicated" is one thing Angular turned people back (to MS camp), another is too many terms and documentation explains them using terms, meaning terms explaining terms, and pretty soon you get lost and frustrated. Powerful doesn't mean complicated and difficult. Simpler, simpler and simpler. Thank you again! – Jeb50 Mar 12 '21 at 17:11
  • @Jeb50 I find it quite simple for it's power. I have seen that it got a lot of hate for being complicated. I think for people switching from AngularJS it's quite easy. I don't like the documentation much either, but when I learned Angular there wasn't anything resembling documentation at all ;-) A lot of complicated is also for jumping on TypeScript early, in hindsight that decision was such wise foresight - ~6 years ago!!. Other complicated stuff is for tree-shaking. They are working on making this easier. That was planned differently at the beginning, but turned out not to work as expected. – Günter Zöchbauer Mar 12 '21 at 18:40
120

[] - Property binding One-way from data source to view target. eg

{{expression}}
[target]="expression"
bind-target="expression"

We can use bind- instead of []

() -> Event Binding One-way from view target to data source

(target)="statement"
on-target="statement"

We can use on- instead of ()

[()]- Two way Binding Banana in a box

[(target)]="expression"
bindon-target="expression"

We can use bindon- instead of [()]

Liam
  • 27,717
  • 28
  • 128
  • 190
Shajin Chandran
  • 1,500
  • 1
  • 11
  • 12
29

As mentioned already, the Angular documentation, especially the "hero tutorial", explains this deeper. Here is the link if you want to check it out.

Parentheses are events of the element you are working on, like the click on a button like your example; this could also be mousedown, keyup, onselect or any action/event for that element, and what is after the = is the name of the method to call -- using the parenthesis for the call. That method should be defined on your component class, i.e.:

<element (event)="method()"></element>

Brackets works the other way. They are to get data from your class -- the opposite of the parenthesis that were sending the event -- so a common example is the usage of a style like this:

<element [ngStyle]="{display:someClassVariable}">

See? You are giving the element a style based on your model/class.

For this you could have used...

<element style="display:{{ModelVariable}};">

The recomendation is that you use double curly brackets for things that you will print on the screen like:

<h1>{{Title}}</h1>

Whatever you use, if you are consistent, it will help the readability of your code.

Lastly, for your * question, it is a longer explanation, but it is very VERY important: It abstracts some methods' implementation that otherwise you would have to do to get an ngFor to work.

One important update is that in the ngFor you will no longer use hash; you need to use let instead as follows:

<tr *ngFor="let movie of movies">
    <td>{{movie.title}}</td>
</tr>

One last thing worth mentioning is that all of the above applies also for your components, e.g. if you create a method in your component, it will be called using ():

<my-owncomponent 
    (onSearched)="MethodToCall()" 
    [MyInputData]="SearchParamsArray"></my-owncomponent>
ruffin
  • 16,507
  • 9
  • 88
  • 138
Gary
  • 602
  • 9
  • 7