64

When I use ?, the binding works well. If I remove it, it doesn't show anything in the view.

<span class="subhead">{{project?.category}}</span>

Can you please tell me the difference? Is it a good practice to use it this way?

Alexander Abakumov
  • 13,617
  • 16
  • 88
  • 129
Sohail Mushtaq Awan
  • 666
  • 1
  • 8
  • 11

3 Answers3

79

When Angular renders the view before project got a value assigned, it causes an exception. ?. stops evaluating when project is null or undefined, which usually happens when data is fetched async, for example from the server which can take quite some time.

The next time change detection recognizes a change, the bindings will be re-evaluated. When project then has a value it will bind project.category.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
36

? is the safe navigation operator. It checks whether the variable is null or undefined so that our template won't try to select a property of something falsy.

More info: https://angular.io/guide/template-syntax#the-safe-navigation-operator----and-null-property-paths

psq
  • 367
  • 5
  • 12
eko
  • 39,722
  • 10
  • 72
  • 98
  • 1
    Small detail... The safe navigation operator is not the same as elvis operator. Elvis operator refers to the ternary operator, which is not the same as safe navigation operator (which I know you know) :) – AT82 Feb 21 '17 at 10:34
  • @AJT_82 ah thank you for the warning! I'll remove it to not cause any confusion. – eko Feb 21 '17 at 10:35
  • Seems like it is an Elvis operator according to to Wikipedia. [Elvis operator is the ternary operator with its second operand omitted](https://en.wikipedia.org/wiki/Elvis_operator). Add it back! Will never remember to call it "safe navigation operator". – rtn Feb 21 '17 at 10:38
  • @echonax No problem. I was educated about this a while back, so I have referred to this wrong myself uptil then :P I also noticed there was this blog post that used the `elvis` operator before (which I have referred to before). Now the blog post has been changed and poster has used `safe navigation operator` instead: http://www.syntaxsuccess.com/viewarticle/elvis-operator-in-angular-2.0 As you can see the url still contains `elvis` operator but content has changed :) – AT82 Feb 21 '17 at 10:41
  • @runyards Let's agree that they're in the same family but it's a strong claim to state that they're the same :-) take a look: http://stackoverflow.com/questions/6613952/is-there-a-null-coalescing-elvis-operator-or-safe-navigation-operator-in-javas – eko Feb 21 '17 at 10:47
  • 1
    Yeah your definitely right, is the equivalent of safe navigation operator. Would be interesting to see how it actually works underneath though. If it returns some default value for various types it would be an evils operator though. – rtn Feb 21 '17 at 11:00
  • Just small correction: Accessing a falsy value's property isn't necessarily bad = producing TypeError. Consider `''.length` which is totally valid operation on falsy value. – Dan Macak May 27 '19 at 08:41
4

This safe navigation operator prevents the view from rendering before getting the value.

We can fix the error of undefined or null values in view templates by the following three methods. Obviously other ways are there.

Method 1: Using Safe navigation operator

<span class="subhead">{{project?.category}}</span>

Method 2: Using async pipe

<span class="subhead">{{(project | async )?.category}}</span>

If you are getting the value through @Input() decorator from app component, you can simplify the code like this in the app component

@Component({
  selector: 'my-app',
  template: `
    <div>
      <app-project [project]="project | async"></app-project>
    </div>
  `,
})
export class App { ... }

And you can use the template as below in the child component(i.e project component for example)

<span class="subhead">{{project.category}}</span>

Method 3: Restricting in the view by *ngIf structural directive

<span class="subhead" *ngIf="project">{{project.category}}</span>

Safe Navigation in angular

Async pipe

Anand Raja
  • 2,676
  • 1
  • 30
  • 35