25

I have used Safe Navigation Operator for Objects to load on Asynchronous calls and it is pretty amazing. I thought I could reproduce the same for Arrays but it displays a template parse error in my Angular code. I know *ngIf is an alternative solution, but is there a more simpler(by code) way just like the Safe Navigation Operator?

<div class="mock">
   <h5>{{data?.title}}</h5>  //This works
   <h6>{{data?.body}}</h6>  //This works
   <h6>{{simpleData?[0]}}</h6>  // This is what I tried to implement    
</div>
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
Sriram Jayaraman
  • 800
  • 1
  • 8
  • 15

4 Answers4

34

Is there something like a Safe Navigation Operator that can be used on Arrays?

Yes, what you are looking for is known as the Optional Chaining operator (JavaScript / TypeScript).

The syntax shown in the MDN JavaScript documentation is:

obj.val?.prop
obj.val?.[expr]
obj.arr?.[index]
obj.func?.(args)

So, to achieve what you want, you need to change your example from:

<h6>{{simpleData?[0]}}</h6>

To:

<h6>{{simpleData?.[0]}}</h6>
                 ^

Also see How to use optional chaining with array in Typescript?.

DavidRR
  • 18,291
  • 25
  • 109
  • 191
12

is there a more simpler(by code) way just like the Safe Navigation Operator?

There is ternary operator.

condition ? expr1 : expr2

<h6>{{simpleData?simpleData[0]:''}}</h6>   
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
  • 1
    This tends to become very unreadable when you have rather complex, deep data: `((a?.b||[])[13]?.c||[])[7]` instead of `a?.b?.[13]?.c?.[7]` in modern ECMAscript – hoeni Oct 30 '20 at 11:36
  • While not exactly Angular-specific, you could also use lodash to safely retrieve more deeply nested objects. e.g. `get myData() { return _.get(this.thing, 'a[0].b.c'); }` https://lodash.com/docs/4.17.15#get – Levi Fuller Dec 14 '20 at 22:27
7

Of cause it's a matter of taste, but in such cases I tend to use a shorter approach:

<h6>{{(simpleData || [])[0]}}</h6>
Alex Vayda
  • 6,154
  • 5
  • 34
  • 50
  • but it is empty array, so accessing first element will fail anyway? – glebsts Jan 07 '20 at 13:49
  • 1
    No it won't. Reading non-existing element returns `undefined` which is translated to an empty result by Angular. – Alex Vayda Feb 04 '20 at 23:14
  • Some might consider using the [Nullish Coalescing operator (??)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator) to now be considered a better practice: `(simpleData ?? [])[0]`. That said, the now available [Optional Chaining operator (?.)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining#syntax) offers a more direct solution to the stated question. – DavidRR Jan 29 '21 at 19:18
0

The other answers amount to the same thing, but I find foo && foo[0] to be the most readable. The right side of the logical-and operator won't be evaluated if the left side is falsy, so you safely get undefined (or I guess null, if you don't believe Douglas Crockford.) with minimal extra characters.

For that matter, you asked for a "simpler" solution, but actually *ngIf is probably correct for the use case you gave. If you use any of the answers here, you'll wind up with an empty h6 tag that you didn't need. If you make the tag itself conditional, you can just put foo[0] in the handlebars and be confident that it won't be evaluated when foo is still undefined, plus you never pollute the page with an empty tag.

Coderer
  • 25,844
  • 28
  • 99
  • 154