feat(common): support as syntax in template/* bindings (#15025)

* feat(common): support `as` syntax in template/* bindings

Closes #15020

Showing the new and the equivalent old syntax.
- `*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”`

* feat(common): convert ngIf to use `*ngIf="exp as local“` syntax

* feat(common): convert ngForOf to use `*ngFor=“let i of exp as local“` syntax

* feat(common): expose NgForOfContext and NgIfContext
This commit is contained in:
Miško Hevery
2017-03-14 20:46:29 -07:00
committed by Chuck Jazdzewski
parent 5fe2d8fd80
commit c10c060d20
12 changed files with 137 additions and 35 deletions

View File

@ -19,7 +19,7 @@ export enum TokenType {
Error
}
const KEYWORDS = ['var', 'let', 'null', 'undefined', 'true', 'false', 'if', 'else', 'this'];
const KEYWORDS = ['var', 'let', 'as', 'null', 'undefined', 'true', 'false', 'if', 'else', 'this'];
@CompilerInjectable()
export class Lexer {
@ -58,6 +58,8 @@ export class Token {
isKeywordLet(): boolean { return this.type == TokenType.Keyword && this.strValue == 'let'; }
isKeywordAs(): boolean { return this.type == TokenType.Keyword && this.strValue == 'as'; }
isKeywordNull(): boolean { return this.type == TokenType.Keyword && this.strValue == 'null'; }
isKeywordUndefined(): boolean {

View File

@ -267,6 +267,7 @@ export class _ParseAST {
}
peekKeywordLet(): boolean { return this.next.isKeywordLet(); }
peekKeywordAs(): boolean { return this.next.isKeywordAs(); }
expectCharacter(code: number) {
if (this.optionalCharacter(code)) return;
@ -686,11 +687,12 @@ export class _ParseAST {
const warnings: string[] = [];
while (this.index < this.tokens.length) {
const start = this.inputIndex;
const keyIsVar: boolean = this.peekKeywordLet();
let keyIsVar: boolean = this.peekKeywordLet();
if (keyIsVar) {
this.advance();
}
let key = this.expectTemplateBindingKey();
let rawKey = this.expectTemplateBindingKey();
let key = rawKey;
if (!keyIsVar) {
if (prefix == null) {
prefix = key;
@ -707,6 +709,12 @@ export class _ParseAST {
} else {
name = '\$implicit';
}
} else if (this.peekKeywordAs()) {
const letStart = this.inputIndex;
this.advance(); // consume `as`
name = rawKey;
key = this.expectTemplateBindingKey(); // read local var name
keyIsVar = true;
} else if (this.next !== EOF && !this.peekKeywordLet()) {
const start = this.inputIndex;
const ast = this.parsePipe();
@ -714,6 +722,12 @@ export class _ParseAST {
expression = new ASTWithSource(ast, source, this.location, this.errors);
}
bindings.push(new TemplateBinding(this.span(start), key, keyIsVar, name, expression));
if (this.peekKeywordAs() && !keyIsVar) {
const letStart = this.inputIndex;
this.advance(); // consume `as`
const letName = this.expectTemplateBindingKey(); // read local var name
bindings.push(new TemplateBinding(this.span(letStart), letName, true, key, null));
}
if (!this.optionalCharacter(chars.$SEMICOLON)) {
this.optionalCharacter(chars.$COMMA);
}