chore: rename Elvis to safe navigation operator

closes #1139
This commit is contained in:
Foxandxss 2016-04-22 22:57:41 +02:00 committed by Ward Bell
parent 0e63b1f39b
commit 4097c67b59
5 changed files with 74 additions and 74 deletions

View File

@ -34,7 +34,7 @@
<a href="#local-vars">Template local variables</a><br>
<a href="#inputs-and-outputs">Inputs and outputs</a><br>
<a href="#pipes">Pipes</a><br>
<a href="#elvis">Elvis <i>?.</i></a><br>
<a href="#safe-navigation-operator">Safe navigation operator <i>?.</i></a><br>
<!--<a href="#enums">Enums</a><br>-->
<!-- Interpolation and expressions -->
@ -738,25 +738,25 @@ bindon-ngModel
<a class="to-toc" href="#toc">top</a>
<!-- Null values and the Elvis operator -->
<hr><h2 id="elvis">Elvis <i>?.</i></h2>
<!-- Null values and the safe navigation operator -->
<hr><h2 id="safe-navigation-operator">Safe navigation operator <i>?.</i></h2>
<div>
<!-- #docregion elvis-1 -->
<!-- #docregion safe-1 -->
The title is {{ title }}
<!-- #enddocregion elvis-1 -->
<!-- #enddocregion safe-1 -->
</div>
<div>
<!-- #docregion elvis-2 -->
<!-- #docregion safe-2 -->
The current hero's name is {{currentHero?.firstName}}
<!-- #enddocregion elvis-2 -->
<!-- #enddocregion safe-2 -->
</div>
<div>
<!-- #docregion elvis-3 -->
<!-- #docregion safe-3 -->
The current hero's name is {{currentHero.firstName}}
<!-- #enddocregion elvis-3 -->
<!-- #enddocregion safe-3 -->
</div>
@ -768,18 +768,18 @@ The null hero's name is {{nullHero.firstName}}
EXCEPTION: The null object does not have a getter 'firstName'.
-->
<!-- #docregion elvis-4 -->
<!-- #docregion safe-4 -->
<!--No hero, div not displayed, no error -->
<div *ngIf="nullHero != null">The null hero's name is {{nullHero.firstName}}</div>
<!-- #enddocregion elvis-4 -->
<!-- #enddocregion safe-4 -->
<!-- skip docregion elvis-5 -->
<!-- skip docregion safe-5 -->
<div>
<!-- #docregion elvis-6 -->
<!-- #docregion safe-6 -->
<!-- No hero, no problem! -->
The null hero's name is {{nullHero?.firstName}}
<!-- #enddocregion elvis-6 -->
<!-- #enddocregion safe-6 -->
</div>

View File

@ -34,7 +34,7 @@
<a href="#local-vars">Template local variables</a><br>
<a href="#inputs-and-outputs">Inputs and outputs</a><br>
<a href="#pipes">Pipes</a><br>
<a href="#elvis">Elvis <i>?.</i></a><br>
<a href="#safe-navigation-operator">Safe navigation operator <i>?.</i></a><br>
<a href="#enums">Enums</a><br>
<!-- Interpolation and expressions -->
@ -739,25 +739,25 @@ After setClasses(), the classes are "{{classDiv.className}}"
<a class="to-toc" href="#toc">top</a>
<!-- Null values and the Elvis operator -->
<hr><h2 id="elvis">Elvis <i>?.</i></h2>
<!-- Null values and the safe navigation operator -->
<hr><h2 id="safe-navigation-operator">Safe navigation operator <i>?.</i></h2>
<div>
<!-- #docregion elvis-1 -->
<!-- #docregion safe-1 -->
The title is {{ title }}
<!-- #enddocregion elvis-1 -->
<!-- #enddocregion safe-1 -->
</div>
<div>
<!-- #docregion elvis-2 -->
<!-- #docregion safe-2 -->
The current hero's name is {{currentHero?.firstName}}
<!-- #enddocregion elvis-2 -->
<!-- #enddocregion safe-2 -->
</div>
<div>
<!-- #docregion elvis-3 -->
<!-- #docregion safe-3 -->
The current hero's name is {{currentHero.firstName}}
<!-- #enddocregion elvis-3 -->
<!-- #enddocregion safe-3 -->
</div>
@ -768,22 +768,22 @@ See console log
TypeError: Cannot read property 'firstName' of null in [null]
-->
<!-- #docregion elvis-4 -->
<!-- #docregion safe-4 -->
<!--No hero, div not displayed, no error -->
<div *ngIf="nullHero">The null hero's name is {{nullHero.firstName}}</div>
<!-- #enddocregion elvis-4 -->
<!-- #enddocregion safe-4 -->
<div>
<!-- #docregion elvis-5 -->
<!-- #docregion safe-5 -->
The null hero's name is {{nullHero && nullHero.firstName}}
<!-- #enddocregion elvis-5 -->
<!-- #enddocregion safe-5 -->
</div>
<div>
<!-- #docregion elvis-6 -->
<!-- #docregion safe-6 -->
<!-- No hero, no problem! -->
The null hero's name is {{nullHero?.firstName}}
<!-- #enddocregion elvis-6 -->
<!-- #enddocregion safe-6 -->
</div>

View File

@ -366,11 +366,11 @@ table
:marked
## Template expression operators
The template expression language employs a subset of Dart syntax supplemented with a few special operators
for specific scenarios. We'll cover two of these operators: _pipe_ and _Elvis_.
for specific scenarios. We'll cover two of these operators: _pipe_ and _safe navigation operator_.
.callout.is-helpful
header Dart difference: ?. is a Dart operator
:marked
The Elvis operator (`?.`) is part of the Dart language.
The safe navigation operator (`?.`) is part of the Dart language.
It's considered a template expression operator because
Angular 2 supports `?.` even in TypeScript and JavaScript apps.
+includeShared('{ts}', 'expression-operators-pipe-1')
@ -383,28 +383,28 @@ table
NOTE: Intentionally omit discussion of the json pipe.
+includeShared('{ts}', 'expression-operators-pipe-4')
+makeExample('template-syntax/dart/lib/app_component.html', 'pipes-json')(format=".")
+includeShared('{ts}', 'expression-operators-elvis-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'elvis-2')(format=".")
+includeShared('{ts}', 'expression-operators-elvis-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'elvis-1')(format=".")
+includeShared('{ts}', 'expression-operators-elvis-3')
// +includeShared('{ts}', 'expression-operators-elvis-4')
+includeShared('{ts}', 'expression-operators-safe-1')
+makeExample('template-syntax/dart/lib/app_component.html', 'safe-2')(format=".")
+includeShared('{ts}', 'expression-operators-safe-2')
+makeExample('template-syntax/dart/lib/app_component.html', 'safe-1')(format=".")
+includeShared('{ts}', 'expression-operators-safe-3')
// +includeShared('{ts}', 'expression-operators-safe-4')
:marked
Dart throws an exception, and so does Angular:
code-example(format="" language="html").
EXCEPTION: The null object does not have a getter 'firstName'.
+includeShared('{ts}', 'expression-operators-elvis-5')
+makeExample('template-syntax/dart/lib/app_component.html', 'elvis-4')(format=".")
+includeShared('{ts}', 'expression-operators-safe-5')
+makeExample('template-syntax/dart/lib/app_component.html', 'safe-4')(format=".")
//
NOTE: Intentionally skip ugly null checking you wouldn't do in Dart.
That means skipping the shared sections 'expression-operators-elvis-6' & 7,
plus the example 'elvis-5'.
That means skipping the shared sections 'expression-operators-safe-6' & 7,
plus the example 'safe-5'.
:marked
This approach has merit but can be cumbersome, especially if the property path is long.
Imagine guarding against a null somewhere in a long property path such as `a.b.c.d`.
+includeShared('{ts}', 'expression-operators-elvis-8')
+makeExample('template-syntax/dart/lib/app_component.html', 'elvis-6')(format=".")
+includeShared('{ts}', 'expression-operators-elvis-9')
+includeShared('{ts}', 'expression-operators-safe-8')
+makeExample('template-syntax/dart/lib/app_component.html', 'safe-6')(format=".")
+includeShared('{ts}', 'expression-operators-safe-9')
+includeShared('{ts}', 'summary')

View File

@ -28,7 +28,7 @@ include ../_util-fns
* [Input and output properties](#inputs-outputs)
* [Template expression operators](#expression-operators)
* [pipe](#pipe)
* ["elvis" (?.)](#elvis)
* ["safe navigation operator" (?.)](#safe-navigation-operator)
// #enddocregion intro
.l-sub-section
:marked
@ -1576,7 +1576,7 @@ figure.image-display
:marked
## Template expression operators
The template expression language employs a subset of JavaScript syntax supplemented with a few special operators
for specific scenarios. We'll cover two of these operators: _pipe_ and _Elvis_.
for specific scenarios. We'll cover two of these operators: _pipe_ and _safe navigation operator_.
// #enddocregion expression-operators
// #docregion expression-operators-pipe-1
@ -1608,23 +1608,23 @@ figure.image-display
// #enddocregion expression-operators-pipe-4
+makeExample('template-syntax/ts/app/app.component.html', 'pipes-json')(format=".")
// #docregion expression-operators-elvis-1
// #docregion expression-operators-safe-1
:marked
<a id="elvis"></a>
### The Elvis operator ( ?. ) and null property paths
<a id="safe-navigation-operator"></a>
### The safe navigation operator ( ?. ) and null property paths
The Angular **Elvis operator (`?.`)** &mdash; perhaps better described as the "safe navigation operator" &mdash; is a fluent and convenient way to guard against null and undefined values in property paths.
The Angular **safe navigation operator (`?.`)** is a fluent and convenient way to guard against null and undefined values in property paths.
Here it is, protecting against a view render failure if the `currentHero` is null.
// #enddocregion expression-operators-elvis-1
+makeExample('template-syntax/ts/app/app.component.html', 'elvis-2')(format=".")
// #docregion expression-operators-elvis-2
// #enddocregion expression-operators-safe-1
+makeExample('template-syntax/ts/app/app.component.html', 'safe-2')(format=".")
// #docregion expression-operators-safe-2
:marked
Lets elaborate on the problem and this particular solution.
What happens when the following data bound `title` property is null?
// #enddocregion expression-operators-elvis-2
+makeExample('template-syntax/ts/app/app.component.html', 'elvis-1')(format=".")
// #docregion expression-operators-elvis-3
// #enddocregion expression-operators-safe-2
+makeExample('template-syntax/ts/app/app.component.html', 'safe-1')(format=".")
// #docregion expression-operators-safe-3
:marked
The view still renders but the displayed value is blank; we see only "The title is" with nothing after it.
That is reasonable behavior. At least the app doesn't crash.
@ -1634,14 +1634,14 @@ figure.image-display
code-example(format="" language="html").
The null hero's name is {{nullHero.firstName}}
// #enddocregion expression-operators-elvis-3
// #docregion expression-operators-elvis-4
// #enddocregion expression-operators-safe-3
// #docregion expression-operators-safe-4
:marked
JavaScript throws a null reference error, and so does Angular:
code-example(format="" language="html").
TypeError: Cannot read property 'firstName' of null in [null]
// #enddocregion expression-operators-elvis-4
// #docregion expression-operators-elvis-5
// #enddocregion expression-operators-safe-4
// #docregion expression-operators-safe-5
:marked
Worse, the *entire view disappears*.
@ -1659,30 +1659,30 @@ code-example(format="" language="html").
Unfortunately, our app crashes when the `currentHero` is null.
We could code around that problem with [NgIf](#ngIf).
// #enddocregion expression-operators-elvis-5
+makeExample('template-syntax/ts/app/app.component.html', 'elvis-4')(format=".")
// #docregion expression-operators-elvis-6
// #enddocregion expression-operators-safe-5
+makeExample('template-syntax/ts/app/app.component.html', 'safe-4')(format=".")
// #docregion expression-operators-safe-6
:marked
Or we could try to chain parts of the property path with `&&`, knowing that the expression bails out
when it encounters the first null.
// #enddocregion expression-operators-elvis-6
+makeExample('template-syntax/ts/app/app.component.html', 'elvis-5')(format=".")
// #docregion expression-operators-elvis-7
// #enddocregion expression-operators-safe-6
+makeExample('template-syntax/ts/app/app.component.html', 'safe-5')(format=".")
// #docregion expression-operators-safe-7
:marked
These approaches have merit but can be cumbersome, especially if the property path is long.
Imagine guarding against a null somewhere in a long property path such as `a.b.c.d`.
// #enddocregion expression-operators-elvis-7
// #docregion expression-operators-elvis-8
// #enddocregion expression-operators-safe-7
// #docregion expression-operators-safe-8
:marked
The Angular Elvis operator (`?.`) is a more fluent and convenient way to guard against nulls in property paths.
The Angular safe navigation operator (`?.`) is a more fluent and convenient way to guard against nulls in property paths.
The expression bails out when it hits the first null value.
The display is blank, but the app keeps rolling without errors.
// #enddocregion expression-operators-elvis-8
+makeExample('template-syntax/ts/app/app.component.html', 'elvis-6')(format=".")
// #docregion expression-operators-elvis-9
// #enddocregion expression-operators-safe-8
+makeExample('template-syntax/ts/app/app.component.html', 'safe-6')(format=".")
// #docregion expression-operators-safe-9
:marked
It works perfectly with long property paths such as `a?.b?.c?.d`.
// #enddocregion expression-operators-elvis-9
// #enddocregion expression-operators-safe-9
// #docregion summary
.l-main-section

View File

@ -1655,7 +1655,7 @@ code-example(format="").
a property expression, as opposed to a literal string.
* We've replaced `ng-repeat`s with `*ngFor`s.
* We've replaced `ng-click` with an event binding for the standard `click`.
* In all references to `phone`, we're using the elvis operator `?.` for
* In all references to `phone`, we're using the safe navigation operator `?.` for
safe property navigation. We need it because when the component first loads,
we don't have `phone` yet and the expressions will refer to a non-existing
value. Unlike in Angular 1, Angular 2 expressions do not fail silently when