diff --git a/aio/content/examples/pipes/src/app/app.component.html b/aio/content/examples/pipes/src/app/app.component.html index b03b8251bc..add2dd2455 100644 --- a/aio/content/examples/pipes/src/app/app.component.html +++ b/aio/content/examples/pipes/src/app/app.component.html @@ -10,6 +10,7 @@ Flying Heroes filter pipe (impure)
Async Hero Message and AsyncPipe
Hero List with caching FetchJsonPipe
+Pipes and Precedence

@@ -80,4 +81,7 @@ -
+
+ + +
diff --git a/aio/content/examples/pipes/src/app/app.module.ts b/aio/content/examples/pipes/src/app/app.module.ts index 8dd502c702..bd551b6fb9 100644 --- a/aio/content/examples/pipes/src/app/app.module.ts +++ b/aio/content/examples/pipes/src/app/app.module.ts @@ -15,6 +15,7 @@ import { HeroBirthday2Component } from './hero-birthday2.component'; import { HeroListComponent } from './hero-list.component'; import { PowerBoostCalculatorComponent } from './power-boost-calculator.component'; import { PowerBoosterComponent } from './power-booster.component'; +import { PrecedenceComponent } from './precedence.component'; @NgModule({ @@ -36,7 +37,8 @@ import { PowerBoosterComponent } from './power-booster.component'; FlyingHeroesPipe, FlyingHeroesImpurePipe, FetchJsonPipe, - ExponentialStrengthPipe + ExponentialStrengthPipe, + PrecedenceComponent ], bootstrap: [AppComponent] }) diff --git a/aio/content/examples/pipes/src/app/precedence.component.html b/aio/content/examples/pipes/src/app/precedence.component.html new file mode 100644 index 0000000000..3b4a208e7e --- /dev/null +++ b/aio/content/examples/pipes/src/app/precedence.component.html @@ -0,0 +1,13 @@ + + +

{{title}}

+ +

Basic uppercase pipe (no precedence considerations necessary): {{ 'text' | uppercase }}

+

The following shows that a pipe has higher precedence than a ternary operator. If the pipe precedence were lower than the ternary operator precedence, the output would be 'TRUE'. Instead it is: {{ true ? 'true' : 'false' | uppercase }}

+

The following shows how parentheses help Angular evaluate the whole statement: + + +{{ (true ? 'true' : 'false') | uppercase }} + +

+ diff --git a/aio/content/examples/pipes/src/app/precedence.component.ts b/aio/content/examples/pipes/src/app/precedence.component.ts new file mode 100644 index 0000000000..c4132c881f --- /dev/null +++ b/aio/content/examples/pipes/src/app/precedence.component.ts @@ -0,0 +1,11 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-precedence', + templateUrl: './precedence.component.html', + styles: [] +}) + +export class PrecedenceComponent { + title = 'Pipes and Precedence'; +} diff --git a/aio/content/guide/architecture-components.md b/aio/content/guide/architecture-components.md index cbe9221411..8f38847295 100644 --- a/aio/content/guide/architecture-components.md +++ b/aio/content/guide/architecture-components.md @@ -126,7 +126,7 @@ Angular pipes let you declare display-value transformations in your template HTM Angular defines various pipes, such as the [date](api/common/DatePipe) pipe and [currency](api/common/CurrencyPipe) pipe; for a complete list, see the [Pipes API list](api?type=pipe). You can also define new pipes. -To specify a value transformation in an HTML template, use the [pipe operator (|)](guide/template-expression-operators#pipe). +To specify a value transformation in an HTML template, use the [pipe operator (|)](guide/pipes). `{{interpolated_value | pipe_name}}` diff --git a/aio/content/guide/built-in-directives.md b/aio/content/guide/built-in-directives.md index 987939144b..c70531358d 100644 --- a/aio/content/guide/built-in-directives.md +++ b/aio/content/guide/built-in-directives.md @@ -265,12 +265,6 @@ The `nullCustomer` will not be displayed as long as it is `null`. -
- -See also the -[safe navigation operator](guide/template-expression-operators#safe-navigation-operator "Safe navigation operator (?.)") below. - -

{@a ngFor} diff --git a/aio/content/guide/pipes.md b/aio/content/guide/pipes.md index 7a49dabffa..8ad1974aae 100644 --- a/aio/content/guide/pipes.md +++ b/aio/content/guide/pipes.md @@ -57,9 +57,7 @@ The tabs in the example show the following: -The component's `birthday` value flows through the -[pipe operator](guide/template-expression-operators#pipe) ( | ) to the [`date`](api/common/DatePipe) -function. +The component's `birthday` value flows through the pipe operator, `|` to the [`date`](api/common/DatePipe) function. {@a parameterizing-a-pipe} @@ -438,3 +436,13 @@ The `fetch` and `fetch-json` pipes display the heroes as shown in Figure 5. The built-in [JsonPipe](api/common/JsonPipe "API description for JsonPipe") provides a way to diagnose a mysteriously failing data binding or to inspect an object for future binding. + +## Pipes and precedence + +The pipe operator has a higher precedence than the ternary operator (`?:`), which means `a ? b : c | x` is parsed as `a ? b : (c | x)`. +The pipe operator cannot be used without parentheses in the first and second operands of `?:`. + +Due to precedence, if you want a pipe to apply to the result of a ternary, wrap the entire expression in parentheses; for example, `(a ? b : c) | x`. + + + diff --git a/aio/content/guide/template-expression-operators.md b/aio/content/guide/template-expression-operators.md index ca392601d5..82633c4354 100644 --- a/aio/content/guide/template-expression-operators.md +++ b/aio/content/guide/template-expression-operators.md @@ -1,13 +1,19 @@ - - # Template expression operators -The Angular template expression language employs a subset of JavaScript syntax supplemented with a few special operators -for specific scenarios. The next sections cover three of these operators: +
-* [pipe](guide/template-expression-operators#pipe) -* [safe navigation operator](guide/template-expression-operators#safe-navigation-operator) -* [non-null assertion operator](guide/template-expression-operators#non-null-assertion-operator) +
Marked for archiving
+ +To ensure that you have the best experience possible, this topic is marked for archiving until we determine that it clearly conveys the most accurate information possible. + +In the meantime, this topic might be helpful: [Hierarchical injectors](guide/hierarchical-dependency-injection). + +If you think this content should not be archived, please file a [GitHub issue](https://github.com/angular/angular/issues/new?template=3-docs-bug.md). + +
+ +The Angular template expression language employs a subset of JavaScript syntax supplemented with a few special operators +for specific scenarios.
@@ -15,111 +21,26 @@ See the for a working example containing the code
-{@a pipe} - -## The pipe operator (`|`) - -The result of an expression might require some transformation before you're ready to use it in a binding. -For example, you might display a number as a currency, change text to uppercase, or filter a list and sort it. - -Pipes are simple functions that accept an input value and return a transformed value. -They're easy to apply within template expressions, using the pipe operator (`|`): - - - -The pipe operator passes the result of an expression on the left to a pipe function on the right. - -You can chain expressions through multiple pipes: - - - -And you can also [apply parameters](guide/pipes#parameterizing-a-pipe) to a pipe: - - - -The `json` pipe is particularly helpful for debugging bindings: - - - -The generated output would look something like this: - - - { "name": "Telephone", - "manufactureDate": "1980-02-25T05:00:00.000Z", - "price": 98 } - - -
- -The pipe operator has a higher precedence than the ternary operator (`?:`), -which means `a ? b : c | x` is parsed as `a ? b : (c | x)`. -Nevertheless, for a number of reasons, -the pipe operator cannot be used without parentheses in the first and second operands of `?:`. -A good practice is to use parentheses in the third operand too. - -
- - -
- -{@a safe-navigation-operator} - -## The safe navigation operator ( `?` ) and null property paths - -The Angular safe navigation operator, `?`, guards against `null` and `undefined` -values in property paths. Here, it protects against a view render failure if `item` is `null`. - - - -If `item` is `null`, the view still renders but the displayed value is blank; you see only "The item name is:" with nothing after it. - -Consider the next example, with a `nullItem`. - - - The null item name is {{nullItem.name}} - - -Since there is no safe navigation operator and `nullItem` is `null`, JavaScript and Angular would throw a `null` reference error and break the rendering process of Angular: - - - TypeError: Cannot read property 'name' of null. - - -Sometimes however, `null` values in the property -path may be OK under certain circumstances, -especially when the value starts out null but the data arrives eventually. - -With the safe navigation operator, `?`, Angular stops evaluating the expression when it hits the first `null` value and renders the view without errors. - -It works perfectly with long property paths such as `a?.b?.c?.d`. - - -
- {@a non-null-assertion-operator} ## The non-null assertion operator ( `!` ) -As of Typescript 2.0, you can enforce [strict null checking](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html "Strict null checking in TypeScript") with the `--strictNullChecks` flag. TypeScript then ensures that no variable is unintentionally `null` or `undefined`. +When you use TypeScript's `--strictNullChecks` flag, you can prevent the type checker from throwing an error with Angular's non-null assertion operator, `!`. -In this mode, typed variables disallow `null` and `undefined` by default. The type checker throws an error if you leave a variable unassigned or try to assign `null` or `undefined` to a variable whose type disallows `null` and `undefined`. +The Angular non-null assertion operator causes the TypeScript type checker to suspend strict `null` and `undefined` checks for a specific property expression. -The type checker also throws an error if it can't determine whether a variable will be `null` or `undefined` at runtime. You tell the type checker not to throw an error by applying the postfix -[non-null assertion operator, !](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html#non-null-assertion-operator "Non-null assertion operator"). - -The Angular non-null assertion operator, `!`, serves the same purpose in -an Angular template. For example, you can assert that `item` properties are also defined. +For example, you can assert that `item` properties are also defined. -When the Angular compiler turns your template into TypeScript code, -it prevents TypeScript from reporting that `item.color` might be `null` or `undefined`. +Often, you want to make sure that any property bindings aren't `null` or `undefined`. +However, there are situations in which such states are acceptable. +For those situations, you can use Angular's non-null assertion operator to prevent TypeScript from reporting that a property is `null` or `undefined`. -Unlike the [_safe navigation operator_](guide/template-expression-operators#safe-navigation-operator "Safe navigation operator (?)"), -the non-null assertion operator does not guard against `null` or `undefined`. -Rather, it tells the TypeScript type checker to suspend strict `null` checks for a specific property expression. +The non-null assertion operator, `!`, is optional unless you turn on strict null checks. + +For more information, see TypeScript's [strict null checking](http://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html "Strict null checking in TypeScript"). -The non-null assertion operator, `!`, is optional with the exception that you must use it when you turn on strict null checks. {@a any-type-cast-function} @@ -131,14 +52,10 @@ the expression to the [`any` type](https://www.typescriptlang.org/docs/handbook/ -When the Angular compiler turns this template into TypeScript code, -it prevents TypeScript from reporting that `bestByDate` is not a member of the `item` -object when it runs type checking on the template. +Using `$any()` prevents TypeScript from reporting that `bestByDate` is not a member of the `item` object. -The `$any()` cast function also works with `this` to allow access to undeclared members of -the component. +The `$any()` cast function also works with `this` to allow access to undeclared members of the component. The `$any()` cast function works anywhere in a binding expression where a method call is valid. - diff --git a/aio/content/guide/template-statements.md b/aio/content/guide/template-statements.md index f6eddc14da..7cabdd7381 100644 --- a/aio/content/guide/template-statements.md +++ b/aio/content/guide/template-statements.md @@ -37,7 +37,7 @@ The following JavaScript and template expression syntax is not allowed: * increment and decrement operators, `++` and `--` * operator assignment, such as `+=` and `-=` * the bitwise operators, such as `|` and `&` -* the [pipe operator](guide/template-expression-operators#pipe) +* the [pipe operator](guide/pipes) ## Statement context diff --git a/aio/content/navigation.json b/aio/content/navigation.json index 581474479e..951e7bca3b 100644 --- a/aio/content/navigation.json +++ b/aio/content/navigation.json @@ -193,9 +193,14 @@ "tooltip": "Introductory guide to sharing data between a class and a template." }, { - "url": "guide/template-expression-operators", - "title": "Template expression operators", - "tooltip": "Introductory guide to transforming data, ensuring safe navigation, and guarding against null variables in templates." + "url": "guide/template-reference-variables", + "title": "Template reference variables", + "tooltip": "Introductory guide to referring to DOM elements within a template." + }, + { + "url": "guide/inputs-outputs", + "title": "Inputs and Outputs", + "tooltip": "Introductory guide to sharing data between parent and child directives or components." }, { "url": "guide/svg-in-templates", diff --git a/packages/common/src/directives/ng_if.ts b/packages/common/src/directives/ng_if.ts index 26704b8592..f525a907d6 100644 --- a/packages/common/src/directives/ng_if.ts +++ b/packages/common/src/directives/ng_if.ts @@ -100,7 +100,7 @@ import {Directive, EmbeddedViewRef, Input, TemplateRef, ViewContainerRef, ɵstri * * The conditional displays the data only if `userStream` returns a value, * so you don't need to use the - * [safe-navigation-operator](guide/template-expression-operators#safe-navigation-operator) (`?.`) + * safe-navigation-operator (`?.`) * to guard against null values when accessing properties. * You can display an alternative template while waiting for the data. *