RFC: `as local-val` syntax proposal
See original GitHub issueAt times it is useful to be able to get a hold of the result of a binding.
<div *ngIf="userStream|async">...</div>
In the above example getting hold userStream|async
is useful so that developer can bind to the value. (see #13061) The current syntax to do that is:
<div *ngIf="userStream|async; let user">...</div>
The above syntax is awkward because it places the let user
on the right hand side. It is also un-natural to use let
in if
since there is no equivalent in JavaScript. The proposed syntax is:
<div *ngIf="expression as varName">...</div>
<div *ngIf="userStream|async as user">...</div>
The above would desugar to:
<template [ngIf]="expression" let-user="ngIf">
as varName
becomeslet-varName="bindingName"
wherebindingName
isngIf
because theexpression
is bound tongIf
This could also be used with ngFor
as:
<div *ngFor="let user of userStream|async as users; let i=index">
{{user}} {{i}} of {{users.length}}
</div>
We could also add ,
for let so that it can become:
<div *ngFor="let i = index, user of userStream|async as users">
{{user}} {{i}} of {{users.length}}
</div>
Alternatively it could be expressed as:
<div *ngFor="let user of userStream|async as users; index as i">
{{user}} {{i}} of {{users.length}}
</div>
Summary
- add
key exp as local
syntax which is equivalent to[key]="exp" var-local="key"
- ensure that
as
syntax can be used even if there is no expression as inindex as i
- ensure that
- add
,
tolet
so that we can do:let localA=exportA, localB=exportB
Breaking Change
The consequence of this change is that we are grabbing as
as a keyword, which means that it can no longer be used for binding. In an unlikely event that someone has created a structural directive which has an as
binding that user would be broken. Example
<div *custom="expr as expr">
would now have different meaning. The fix would be to add ;
like so:
<div *custom="expr; as expr">
Clarification
These are equivalent
*ngIf="exp as var1"
=>*ngIf="exp; let var1 = ngIf"
*ngFor="var item of itemsStream |async as items"
=>*ngFor="var item of itemsStream |async; let items = ngForOf"
Issue Analytics
- State:
- Created 7 years ago
- Reactions:69
- Comments:36 (25 by maintainers)
+1. In general, I am worried that our syntax is very permissive, i.e. allows many cases that are usually unintended errors by users. Maybe we should revisit our micro syntax for v5 to make it more strict and give users better error messages.
@netstart there were issues over this dating back to AngularJS whether promises were automatically unwrapped or not, I much prefer being explicit when using observables especially because at times I find it helpful to pass an observable to a child component rather than just the latest value.
As for the proposed syntax, I like the use of the
as
keyword because it accomplishes two things. It provides clear syntax for referencing values and it alleviates multiple subscriptions to observables by eliminating the need to use the async pipe in multiple places.This has the added benefit of reducing the use of the
share
operator in component’s code which is really a concern of the view and not of component’s logic.