Compare commits
18 Commits
Author | SHA1 | Date | |
---|---|---|---|
a7d28044c5 | |||
055bea2969 | |||
dad0d21b89 | |||
313683f6f3 | |||
338be6d6a5 | |||
4b56f79328 | |||
d7f2a3c71b | |||
1c929ae244 | |||
83d0ff6d13 | |||
d43e5dd44d | |||
61ba223c1a | |||
6164eb25f3 | |||
5e9d3dba3a | |||
16922655ca | |||
7dc12b93fe | |||
1c82b58185 | |||
d6c414c08f | |||
d25d1730c7 |
32
.pullapprove.yml
Normal file
32
.pullapprove.yml
Normal file
@ -0,0 +1,32 @@
|
||||
# Configuration for pullapprove.com
|
||||
# See ownership spreadsheet:
|
||||
# https://docs.google.com/spreadsheets/d/1-HIlzfbPYGsPr9KuYMe6bLfc4LXzPjpoALqtYRYTZB0/edit?pli=1#gid=0&vpid=A5
|
||||
|
||||
version: 2
|
||||
|
||||
group_defaults:
|
||||
required: 1
|
||||
reset_on_reopened:
|
||||
enabled: true
|
||||
approve_by_comment:
|
||||
enabled: true
|
||||
approve_regex: '^(Approved|:\+1:|LGTM)'
|
||||
|
||||
groups:
|
||||
config:
|
||||
conditions:
|
||||
files:
|
||||
- "*.yml"
|
||||
- "*.json"
|
||||
teams:
|
||||
- repoowners
|
||||
|
||||
compiler:
|
||||
conditions:
|
||||
files:
|
||||
- "tools/@angular/tsc-wrapped/*"
|
||||
- "modules/@angular/compiler/*"
|
||||
- "modules/@angular/compiler-cli/*"
|
||||
teams:
|
||||
- compiler-owners
|
||||
- repoowners
|
17
CHANGELOG.md
17
CHANGELOG.md
@ -1,3 +1,20 @@
|
||||
<a name="2.4.3"></a>
|
||||
## [2.4.3](https://github.com/angular/angular/compare/2.4.2...2.4.3) (2017-01-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **compiler:** avoid evaluating arguments to unknown decorators ([5e9d3db](https://github.com/angular/angular/commit/5e9d3db)), closes [#13605](https://github.com/angular/angular/issues/13605)
|
||||
* **compiler:** fix template binding parsing (`*directive="-..."`) ([7dc12b9](https://github.com/angular/angular/commit/7dc12b9)), closes [#13800](https://github.com/angular/angular/issues/13800)
|
||||
* **compiler-cli:** add support for more than 2 levels of nested lazy routes ([6164eb2](https://github.com/angular/angular/commit/6164eb2)), closes [angular/angular-cli#3663](https://github.com/angular/angular-cli/issues/3663)
|
||||
* **compiler-cli:** avoid handling functions in loadChildren as lazy load routes paths ([313683f](https://github.com/angular/angular/commit/313683f)), closes [angular/angular-cli#3204](https://github.com/angular/angular-cli/issues/3204)
|
||||
* **i18n:** translate attributes inside elements marked for translation ([d7f2a3c](https://github.com/angular/angular/commit/d7f2a3c))
|
||||
* **router:** RouterLink mirrors input `target` as attribute ([1c82b58](https://github.com/angular/angular/commit/1c82b58)), closes [#13837](https://github.com/angular/angular/issues/13837)
|
||||
* **router:** throw an error when navigate to null/undefined path ([61ba223](https://github.com/angular/angular/commit/61ba223)), closes [#10560](https://github.com/angular/angular/issues/10560) [#13384](https://github.com/angular/angular/issues/13384)
|
||||
* **router:** fix checking for object intersection ([1692265](https://github.com/angular/angular/commit/1692265))
|
||||
|
||||
|
||||
|
||||
<a name="2.4.2"></a>
|
||||
## [2.4.2](https://github.com/angular/angular/compare/2.4.1...2.4.2) (2017-01-06)
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
import {CollectionChangeRecord, Directive, DoCheck, ElementRef, Input, IterableDiffer, IterableDiffers, KeyValueChangeRecord, KeyValueDiffer, KeyValueDiffers, Renderer} from '@angular/core';
|
||||
|
||||
import {isListLikeIterable} from '../facade/collection';
|
||||
import {isPresent, stringify} from '../facade/lang';
|
||||
import {stringify} from '../facade/lang';
|
||||
|
||||
/**
|
||||
* @ngModule CommonModule
|
||||
@ -134,7 +134,7 @@ export class NgClass implements DoCheck {
|
||||
(<any>rawClassVal).forEach((klass: string) => this._toggleClass(klass, !isCleanup));
|
||||
} else {
|
||||
Object.keys(rawClassVal).forEach(klass => {
|
||||
if (isPresent(rawClassVal[klass])) this._toggleClass(klass, !isCleanup);
|
||||
if (rawClassVal[klass] != null) this._toggleClass(klass, !isCleanup);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -21,10 +21,9 @@ import {SwitchView} from './ng_switch';
|
||||
* @howToUse
|
||||
* ```
|
||||
* <some-element [ngPlural]="value">
|
||||
* <ng-container *ngPluralCase="'=0'">there is nothing</ng-container>
|
||||
* <ng-container *ngPluralCase="'=1'">there is one</ng-container>
|
||||
* <ng-container *ngPluralCase="'few'">there are a few</ng-container>
|
||||
* <ng-container *ngPluralCase="'other'">there are exactly #</ng-container>
|
||||
* <template ngPluralCase="=0">there is nothing</template>
|
||||
* <template ngPluralCase="=1">there is one</template>
|
||||
* <template ngPluralCase="few">there are a few</template>
|
||||
* </some-element>
|
||||
* ```
|
||||
*
|
||||
@ -90,8 +89,8 @@ export class NgPlural {
|
||||
* @howToUse
|
||||
* ```
|
||||
* <some-element [ngPlural]="value">
|
||||
* <ng-container *ngPluralCase="'=0'">...</ng-container>
|
||||
* <ng-container *ngPluralCase="'other'">...</ng-container>
|
||||
* <template ngPluralCase="=0">...</template>
|
||||
* <template ngPluralCase="other">...</template>
|
||||
* </some-element>
|
||||
*```
|
||||
*
|
||||
|
@ -7,7 +7,6 @@
|
||||
*/
|
||||
|
||||
import {Pipe, PipeTransform} from '@angular/core';
|
||||
import {isBlank} from '../facade/lang';
|
||||
import {NgLocalization, getPluralCategory} from '../localization';
|
||||
import {InvalidPipeArgumentError} from './invalid_pipe_argument_error';
|
||||
|
||||
@ -35,7 +34,7 @@ export class I18nPluralPipe implements PipeTransform {
|
||||
constructor(private _localization: NgLocalization) {}
|
||||
|
||||
transform(value: number, pluralMap: {[count: string]: string}): string {
|
||||
if (isBlank(value)) return '';
|
||||
if (value == null) return '';
|
||||
|
||||
if (typeof pluralMap !== 'object' || pluralMap === null) {
|
||||
throw new InvalidPipeArgumentError(I18nPluralPipe, pluralMap);
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
import {Inject, LOCALE_ID, Pipe, PipeTransform, Type} from '@angular/core';
|
||||
|
||||
import {NumberWrapper, isBlank, isPresent} from '../facade/lang';
|
||||
import {NumberWrapper} from '../facade/lang';
|
||||
|
||||
import {NumberFormatStyle, NumberFormatter} from './intl';
|
||||
import {InvalidPipeArgumentError} from './invalid_pipe_argument_error';
|
||||
@ -18,7 +18,7 @@ const _NUMBER_FORMAT_REGEXP = /^(\d+)?\.((\d+)(-(\d+))?)?$/;
|
||||
function formatNumber(
|
||||
pipe: Type<any>, locale: string, value: number | string, style: NumberFormatStyle,
|
||||
digits: string, currency: string = null, currencyAsSymbol: boolean = false): string {
|
||||
if (isBlank(value)) return null;
|
||||
if (value == null) return null;
|
||||
|
||||
// Convert strings to numbers
|
||||
value = typeof value === 'string' && NumberWrapper.isNumeric(value) ? +value : value;
|
||||
@ -41,13 +41,13 @@ function formatNumber(
|
||||
if (parts === null) {
|
||||
throw new Error(`${digits} is not a valid digit info for number pipes`);
|
||||
}
|
||||
if (isPresent(parts[1])) { // min integer digits
|
||||
if (parts[1] != null) { // min integer digits
|
||||
minInt = NumberWrapper.parseIntAutoRadix(parts[1]);
|
||||
}
|
||||
if (isPresent(parts[3])) { // min fraction digits
|
||||
if (parts[3] != null) { // min fraction digits
|
||||
minFraction = NumberWrapper.parseIntAutoRadix(parts[3]);
|
||||
}
|
||||
if (isPresent(parts[5])) { // max fraction digits
|
||||
if (parts[5] != null) { // max fraction digits
|
||||
maxFraction = NumberWrapper.parseIntAutoRadix(parts[5]);
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,6 @@
|
||||
*/
|
||||
|
||||
import {Pipe, PipeTransform} from '@angular/core';
|
||||
import {isBlank} from '../facade/lang';
|
||||
import {InvalidPipeArgumentError} from './invalid_pipe_argument_error';
|
||||
|
||||
/**
|
||||
@ -58,7 +57,7 @@ import {InvalidPipeArgumentError} from './invalid_pipe_argument_error';
|
||||
@Pipe({name: 'slice', pure: false})
|
||||
export class SlicePipe implements PipeTransform {
|
||||
transform(value: any, start: number, end?: number): any {
|
||||
if (isBlank(value)) return value;
|
||||
if (value == null) return value;
|
||||
|
||||
if (!this.supports(value)) {
|
||||
throw new InvalidPipeArgumentError(SlicePipe, value);
|
||||
|
@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {Component, ContentChild, TemplateRef} from '@angular/core';
|
||||
import {Component} from '@angular/core';
|
||||
import {ComponentFixture, TestBed, async} from '@angular/core/testing';
|
||||
import {By} from '@angular/platform-browser/src/dom/debug/by';
|
||||
import {expect} from '@angular/platform-browser/testing/matchers';
|
||||
@ -29,10 +29,7 @@ export function main() {
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
TestComponent,
|
||||
ComponentUsingTestComponent,
|
||||
],
|
||||
declarations: [TestComponent],
|
||||
imports: [CommonModule],
|
||||
});
|
||||
});
|
||||
@ -77,7 +74,7 @@ export function main() {
|
||||
}));
|
||||
|
||||
it('should iterate over an array of objects', async(() => {
|
||||
const template = '<ul><li template="ngFor let item of items">{{item["name"]}};</li></ul>';
|
||||
const template = '<ul><li *ngFor="let item of items">{{item["name"]}};</li></ul>';
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
// INIT
|
||||
@ -95,7 +92,7 @@ export function main() {
|
||||
}));
|
||||
|
||||
it('should gracefully handle nulls', async(() => {
|
||||
const template = '<ul><li template="ngFor let item of null">{{item}};</li></ul>';
|
||||
const template = '<ul><li *ngFor="let item of null">{{item}};</li></ul>';
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
detectChangesAndExpectText('');
|
||||
@ -140,12 +137,8 @@ export function main() {
|
||||
}));
|
||||
|
||||
it('should repeat over nested arrays', async(() => {
|
||||
const template = '<div>' +
|
||||
'<div template="ngFor let item of items">' +
|
||||
'<div template="ngFor let subitem of item">' +
|
||||
'{{subitem}}-{{item.length}};' +
|
||||
'</div>|' +
|
||||
'</div>' +
|
||||
const template = '<div *ngFor="let item of items">' +
|
||||
'<div *ngFor="let subitem of item">{{subitem}}-{{item.length}};</div>|' +
|
||||
'</div>';
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
@ -157,10 +150,9 @@ export function main() {
|
||||
}));
|
||||
|
||||
it('should repeat over nested arrays with no intermediate element', async(() => {
|
||||
const template = '<div><template ngFor let-item [ngForOf]="items">' +
|
||||
'<div template="ngFor let subitem of item">' +
|
||||
'{{subitem}}-{{item.length}};' +
|
||||
'</div></template></div>';
|
||||
const template = '<div *ngFor="let item of items">' +
|
||||
'<div *ngFor="let subitem of item">{{subitem}}-{{item.length}};</div>' +
|
||||
'</div>';
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
getComponent().items = [['a', 'b'], ['c']];
|
||||
@ -170,10 +162,11 @@ export function main() {
|
||||
detectChangesAndExpectText('e-1;f-2;g-2;');
|
||||
}));
|
||||
|
||||
it('should repeat over nested ngIf that are the last node in the ngFor temlate', async(() => {
|
||||
const template =
|
||||
`<div><template ngFor let-item [ngForOf]="items" let-i="index"><div>{{i}}|</div>` +
|
||||
`<div *ngIf="i % 2 == 0">even|</div></template></div>`;
|
||||
it('should repeat over nested ngIf that are the last node in the ngFor template', async(() => {
|
||||
const template = `<div *ngFor="let item of items; let i=index">` +
|
||||
`<div>{{i}}|</div>` +
|
||||
`<div *ngIf="i % 2 == 0">even|</div>` +
|
||||
`</div>`;
|
||||
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
@ -189,8 +182,7 @@ export function main() {
|
||||
}));
|
||||
|
||||
it('should display indices correctly', async(() => {
|
||||
const template =
|
||||
'<div><span template="ngFor: let item of items; let i=index">{{i.toString()}}</span></div>';
|
||||
const template = '<span *ngFor ="let item of items; let i=index">{{i.toString()}}</span>';
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
getComponent().items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
@ -202,7 +194,7 @@ export function main() {
|
||||
|
||||
it('should display first item correctly', async(() => {
|
||||
const template =
|
||||
'<div><span template="ngFor: let item of items; let isFirst=first">{{isFirst.toString()}}</span></div>';
|
||||
'<span *ngFor="let item of items; let isFirst=first">{{isFirst.toString()}}</span>';
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
getComponent().items = [0, 1, 2];
|
||||
@ -214,7 +206,7 @@ export function main() {
|
||||
|
||||
it('should display last item correctly', async(() => {
|
||||
const template =
|
||||
'<div><span template="ngFor: let item of items; let isLast=last">{{isLast.toString()}}</span></div>';
|
||||
'<span *ngFor="let item of items; let isLast=last">{{isLast.toString()}}</span>';
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
getComponent().items = [0, 1, 2];
|
||||
@ -226,7 +218,7 @@ export function main() {
|
||||
|
||||
it('should display even items correctly', async(() => {
|
||||
const template =
|
||||
'<div><span template="ngFor: let item of items; let isEven=even">{{isEven.toString()}}</span></div>';
|
||||
'<span *ngFor="let item of items; let isEven=even">{{isEven.toString()}}</span>';
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
getComponent().items = [0, 1, 2];
|
||||
@ -238,7 +230,7 @@ export function main() {
|
||||
|
||||
it('should display odd items correctly', async(() => {
|
||||
const template =
|
||||
'<div><span template="ngFor: let item of items; let isOdd=odd">{{isOdd.toString()}}</span></div>';
|
||||
'<span *ngFor="let item of items; let isOdd=odd">{{isOdd.toString()}}</span>';
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
getComponent().items = [0, 1, 2, 3];
|
||||
@ -249,55 +241,38 @@ export function main() {
|
||||
}));
|
||||
|
||||
it('should allow to use a custom template', async(() => {
|
||||
const tcTemplate =
|
||||
'<ul><template ngFor [ngForOf]="items" [ngForTemplate]="contentTpl"></template></ul>';
|
||||
TestBed.overrideComponent(TestComponent, {set: {template: tcTemplate}});
|
||||
const cutTemplate =
|
||||
'<test-cmp><li template="let item; let i=index">{{i}}: {{item}};</li></test-cmp>';
|
||||
TestBed.overrideComponent(ComponentUsingTestComponent, {set: {template: cutTemplate}});
|
||||
fixture = TestBed.createComponent(ComponentUsingTestComponent);
|
||||
|
||||
const testComponent = fixture.debugElement.children[0];
|
||||
testComponent.componentInstance.items = ['a', 'b', 'c'];
|
||||
const template =
|
||||
'<ng-container *ngFor="let item of items; template: tpl"></ng-container>' +
|
||||
'<template let-item let-i="index" #tpl><p>{{i}}: {{item}};</p></template>';
|
||||
fixture = createTestComponent(template);
|
||||
getComponent().items = ['a', 'b', 'c'];
|
||||
fixture.detectChanges();
|
||||
expect(testComponent.nativeElement).toHaveText('0: a;1: b;2: c;');
|
||||
detectChangesAndExpectText('0: a;1: b;2: c;');
|
||||
}));
|
||||
|
||||
it('should use a default template if a custom one is null', async(() => {
|
||||
const testTemplate = `<ul><template ngFor let-item [ngForOf]="items"
|
||||
[ngForTemplate]="contentTpl" let-i="index">{{i}}: {{item}};</template></ul>`;
|
||||
TestBed.overrideComponent(TestComponent, {set: {template: testTemplate}});
|
||||
const cutTemplate =
|
||||
'<test-cmp><li template="let item; let i=index">{{i}}: {{item}};</li></test-cmp>';
|
||||
TestBed.overrideComponent(ComponentUsingTestComponent, {set: {template: cutTemplate}});
|
||||
fixture = TestBed.createComponent(ComponentUsingTestComponent);
|
||||
|
||||
const testComponent = fixture.debugElement.children[0];
|
||||
testComponent.componentInstance.items = ['a', 'b', 'c'];
|
||||
const template =
|
||||
`<ul><ng-container *ngFor="let item of items; template: null; let i=index">{{i}}: {{item}};</ng-container></ul>`;
|
||||
fixture = createTestComponent(template);
|
||||
getComponent().items = ['a', 'b', 'c'];
|
||||
fixture.detectChanges();
|
||||
expect(testComponent.nativeElement).toHaveText('0: a;1: b;2: c;');
|
||||
detectChangesAndExpectText('0: a;1: b;2: c;');
|
||||
}));
|
||||
|
||||
it('should use a custom template when both default and a custom one are present', async(() => {
|
||||
const testTemplate = `<ul><template ngFor let-item [ngForOf]="items"
|
||||
[ngForTemplate]="contentTpl" let-i="index">{{i}}=> {{item}};</template></ul>`;
|
||||
TestBed.overrideComponent(TestComponent, {set: {template: testTemplate}});
|
||||
const cutTemplate =
|
||||
'<test-cmp><li template="let item; let i=index">{{i}}: {{item}};</li></test-cmp>';
|
||||
TestBed.overrideComponent(ComponentUsingTestComponent, {set: {template: cutTemplate}});
|
||||
fixture = TestBed.createComponent(ComponentUsingTestComponent);
|
||||
|
||||
const testComponent = fixture.debugElement.children[0];
|
||||
testComponent.componentInstance.items = ['a', 'b', 'c'];
|
||||
const template =
|
||||
'<ng-container *ngFor="let item of items; template: tpl">{{i}};</ng-container>' +
|
||||
'<template let-item let-i="index" #tpl>{{i}}: {{item}};</template>';
|
||||
fixture = createTestComponent(template);
|
||||
getComponent().items = ['a', 'b', 'c'];
|
||||
fixture.detectChanges();
|
||||
expect(testComponent.nativeElement).toHaveText('0: a;1: b;2: c;');
|
||||
detectChangesAndExpectText('0: a;1: b;2: c;');
|
||||
}));
|
||||
|
||||
describe('track by', () => {
|
||||
it('should console.warn if trackBy is not a function', async(() => {
|
||||
// TODO(vicb): expect a warning message when we have a proper log service
|
||||
const template =
|
||||
`<template ngFor let-item [ngForOf]="items" [ngForTrackBy]="value"></template>`;
|
||||
const template = `<p *ngFor="let item of items; trackBy: value"></p>`;
|
||||
fixture = createTestComponent(template);
|
||||
fixture.componentInstance.value = 0;
|
||||
fixture.detectChanges();
|
||||
@ -305,8 +280,7 @@ export function main() {
|
||||
|
||||
it('should track by identity when trackBy is to `null` or `undefined`', async(() => {
|
||||
// TODO(vicb): expect no warning message when we have a proper log service
|
||||
const template =
|
||||
`<template ngFor let-item [ngForOf]="items" [ngForTrackBy]="value">{{ item }}</template>`;
|
||||
const template = `<p *ngFor="let item of items; trackBy: value">{{ item }}</p>`;
|
||||
fixture = createTestComponent(template);
|
||||
fixture.componentInstance.items = ['a', 'b', 'c'];
|
||||
fixture.componentInstance.value = null;
|
||||
@ -317,7 +291,7 @@ export function main() {
|
||||
|
||||
it('should set the context to the component instance', async(() => {
|
||||
const template =
|
||||
`<template ngFor let-item [ngForOf]="items" [ngForTrackBy]="trackByContext.bind(this)"></template>`;
|
||||
`<p *ngFor="let item of items; trackBy: trackByContext.bind(this)"></p>`;
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
thisArg = null;
|
||||
@ -327,9 +301,7 @@ export function main() {
|
||||
|
||||
it('should not replace tracked items', async(() => {
|
||||
const template =
|
||||
`<template ngFor let-item [ngForOf]="items" [ngForTrackBy]="trackById" let-i="index">
|
||||
<p>{{items[i]}}</p>
|
||||
</template>`;
|
||||
`<p *ngFor="let item of items; trackBy: trackById; let i=index">{{items[i]}}</p>`;
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
const buildItemList = () => {
|
||||
@ -345,7 +317,7 @@ export function main() {
|
||||
|
||||
it('should update implicit local variable on view', async(() => {
|
||||
const template =
|
||||
`<div><template ngFor let-item [ngForOf]="items" [ngForTrackBy]="trackById">{{item['color']}}</template></div>`;
|
||||
`<div *ngFor="let item of items; trackBy: trackById">{{item['color']}}</div>`;
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
getComponent().items = [{'id': 'a', 'color': 'blue'}];
|
||||
@ -357,7 +329,7 @@ export function main() {
|
||||
|
||||
it('should move items around and keep them updated ', async(() => {
|
||||
const template =
|
||||
`<div><template ngFor let-item [ngForOf]="items" [ngForTrackBy]="trackById">{{item['color']}}</template></div>`;
|
||||
`<div *ngFor="let item of items; trackBy: trackById">{{item['color']}}</div>`;
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
getComponent().items = [{'id': 'a', 'color': 'blue'}, {'id': 'b', 'color': 'yellow'}];
|
||||
@ -368,8 +340,7 @@ export function main() {
|
||||
}));
|
||||
|
||||
it('should handle added and removed items properly when tracking by index', async(() => {
|
||||
const template =
|
||||
`<div><template ngFor let-item [ngForOf]="items" [ngForTrackBy]="trackByIndex">{{item}}</template></div>`;
|
||||
const template = `<div *ngFor="let item of items; trackBy: trackByIndex">{{item}}</div>`;
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
getComponent().items = ['a', 'b', 'c', 'd'];
|
||||
@ -389,7 +360,6 @@ class Foo {
|
||||
|
||||
@Component({selector: 'test-cmp', template: ''})
|
||||
class TestComponent {
|
||||
@ContentChild(TemplateRef) contentTpl: TemplateRef<Object>;
|
||||
value: any;
|
||||
items: any[] = [1, 2];
|
||||
trackById(index: number, item: any): string { return item['id']; }
|
||||
@ -397,12 +367,7 @@ class TestComponent {
|
||||
trackByContext(): void { thisArg = this; }
|
||||
}
|
||||
|
||||
@Component({selector: 'outer-cmp', template: ''})
|
||||
class ComponentUsingTestComponent {
|
||||
items: any = [1, 2];
|
||||
}
|
||||
|
||||
const TEMPLATE = '<div><span template="ngFor let item of items">{{item.toString()}};</span></div>';
|
||||
const TEMPLATE = '<div><span *ngFor="let item of items">{{item.toString()}};</span></div>';
|
||||
|
||||
function createTestComponent(template: string = TEMPLATE): ComponentFixture<TestComponent> {
|
||||
return TestBed.overrideComponent(TestComponent, {set: {template: template}})
|
||||
|
@ -9,6 +9,7 @@
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {Component} from '@angular/core';
|
||||
import {ComponentFixture, TestBed, async} from '@angular/core/testing';
|
||||
import {By} from '@angular/platform-browser/src/dom/debug/by';
|
||||
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
|
||||
import {expect} from '@angular/platform-browser/testing/matchers';
|
||||
|
||||
@ -28,131 +29,114 @@ export function main() {
|
||||
});
|
||||
|
||||
it('should work in a template attribute', async(() => {
|
||||
const template = '<div><span template="ngIf booleanCondition">hello</span></div>';
|
||||
const template = '<span *ngIf="booleanCondition">hello</span>';
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(1);
|
||||
expect(fixture.debugElement.queryAll(By.css('span')).length).toEqual(1);
|
||||
expect(fixture.nativeElement).toHaveText('hello');
|
||||
}));
|
||||
|
||||
it('should work in a template element', async(() => {
|
||||
const template =
|
||||
'<div><template [ngIf]="booleanCondition"><span>hello2</span></template></div>';
|
||||
|
||||
it('should work on a template element', async(() => {
|
||||
const template = '<template [ngIf]="booleanCondition">hello2</template>';
|
||||
fixture = createTestComponent(template);
|
||||
fixture.detectChanges();
|
||||
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(1);
|
||||
expect(fixture.nativeElement).toHaveText('hello2');
|
||||
}));
|
||||
|
||||
it('should toggle node when condition changes', async(() => {
|
||||
const template = '<div><span template="ngIf booleanCondition">hello</span></div>';
|
||||
|
||||
const template = '<span *ngIf="booleanCondition">hello</span>';
|
||||
fixture = createTestComponent(template);
|
||||
getComponent().booleanCondition = false;
|
||||
fixture.detectChanges();
|
||||
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(0);
|
||||
expect(fixture.debugElement.queryAll(By.css('span')).length).toEqual(0);
|
||||
expect(fixture.nativeElement).toHaveText('');
|
||||
|
||||
getComponent().booleanCondition = true;
|
||||
fixture.detectChanges();
|
||||
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(1);
|
||||
expect(fixture.debugElement.queryAll(By.css('span')).length).toEqual(1);
|
||||
expect(fixture.nativeElement).toHaveText('hello');
|
||||
|
||||
getComponent().booleanCondition = false;
|
||||
fixture.detectChanges();
|
||||
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(0);
|
||||
expect(fixture.debugElement.queryAll(By.css('span')).length).toEqual(0);
|
||||
expect(fixture.nativeElement).toHaveText('');
|
||||
}));
|
||||
|
||||
it('should handle nested if correctly', async(() => {
|
||||
const template =
|
||||
'<div><template [ngIf]="booleanCondition"><span *ngIf="nestedBooleanCondition">hello</span></template></div>';
|
||||
'<div *ngIf="booleanCondition"><span *ngIf="nestedBooleanCondition">hello</span></div>';
|
||||
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
getComponent().booleanCondition = false;
|
||||
fixture.detectChanges();
|
||||
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(0);
|
||||
expect(fixture.debugElement.queryAll(By.css('span')).length).toEqual(0);
|
||||
expect(fixture.nativeElement).toHaveText('');
|
||||
|
||||
getComponent().booleanCondition = true;
|
||||
fixture.detectChanges();
|
||||
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(1);
|
||||
expect(fixture.debugElement.queryAll(By.css('span')).length).toEqual(1);
|
||||
expect(fixture.nativeElement).toHaveText('hello');
|
||||
|
||||
getComponent().nestedBooleanCondition = false;
|
||||
fixture.detectChanges();
|
||||
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(0);
|
||||
expect(fixture.debugElement.queryAll(By.css('span')).length).toEqual(0);
|
||||
expect(fixture.nativeElement).toHaveText('');
|
||||
|
||||
getComponent().nestedBooleanCondition = true;
|
||||
fixture.detectChanges();
|
||||
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(1);
|
||||
expect(fixture.debugElement.queryAll(By.css('span')).length).toEqual(1);
|
||||
expect(fixture.nativeElement).toHaveText('hello');
|
||||
|
||||
getComponent().booleanCondition = false;
|
||||
fixture.detectChanges();
|
||||
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(0);
|
||||
expect(fixture.debugElement.queryAll(By.css('span')).length).toEqual(0);
|
||||
expect(fixture.nativeElement).toHaveText('');
|
||||
}));
|
||||
|
||||
it('should update several nodes with if', async(() => {
|
||||
const template = '<div>' +
|
||||
'<span template="ngIf numberCondition + 1 >= 2">helloNumber</span>' +
|
||||
'<span template="ngIf stringCondition == \'foo\'">helloString</span>' +
|
||||
'<span template="ngIf functionCondition(stringCondition, numberCondition)">helloFunction</span>' +
|
||||
'</div>';
|
||||
const template = '<span *ngIf="numberCondition + 1 >= 2">helloNumber</span>' +
|
||||
'<span *ngIf="stringCondition == \'foo\'">helloString</span>' +
|
||||
'<span *ngIf="functionCondition(stringCondition, numberCondition)">helloFunction</span>';
|
||||
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(3);
|
||||
expect(fixture.debugElement.queryAll(By.css('span')).length).toEqual(3);
|
||||
expect(getDOM().getText(fixture.nativeElement))
|
||||
.toEqual('helloNumberhelloStringhelloFunction');
|
||||
|
||||
getComponent().numberCondition = 0;
|
||||
fixture.detectChanges();
|
||||
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(1);
|
||||
expect(fixture.debugElement.queryAll(By.css('span')).length).toEqual(1);
|
||||
expect(fixture.nativeElement).toHaveText('helloString');
|
||||
|
||||
getComponent().numberCondition = 1;
|
||||
getComponent().stringCondition = 'bar';
|
||||
fixture.detectChanges();
|
||||
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(1);
|
||||
expect(fixture.debugElement.queryAll(By.css('span')).length).toEqual(1);
|
||||
expect(fixture.nativeElement).toHaveText('helloNumber');
|
||||
}));
|
||||
|
||||
it('should not add the element twice if the condition goes from true to true (JS)',
|
||||
async(() => {
|
||||
const template = '<div><span template="ngIf numberCondition">hello</span></div>';
|
||||
it('should not add the element twice if the condition goes from truthy to truthy', async(() => {
|
||||
const template = '<span *ngIf="numberCondition">hello</span>';
|
||||
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(1);
|
||||
let els = fixture.debugElement.queryAll(By.css('span'));
|
||||
expect(els.length).toEqual(1);
|
||||
getDOM().addClass(els[0].nativeElement, 'marker');
|
||||
expect(fixture.nativeElement).toHaveText('hello');
|
||||
|
||||
getComponent().numberCondition = 2;
|
||||
fixture.detectChanges();
|
||||
expect(getDOM().querySelectorAll(fixture.nativeElement, 'span').length).toEqual(1);
|
||||
els = fixture.debugElement.queryAll(By.css('span'));
|
||||
expect(els.length).toEqual(1);
|
||||
expect(getDOM().hasClass(els[0].nativeElement, 'marker')).toBe(true);
|
||||
|
||||
expect(fixture.nativeElement).toHaveText('hello');
|
||||
}));
|
||||
|
||||
it('should not recreate the element if the condition goes from true to true (JS)', async(() => {
|
||||
const template = '<div><span template="ngIf numberCondition">hello</span></div>';
|
||||
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
fixture.detectChanges();
|
||||
getDOM().addClass(getDOM().querySelector(fixture.nativeElement, 'span'), 'foo');
|
||||
|
||||
getComponent().numberCondition = 2;
|
||||
fixture.detectChanges();
|
||||
expect(getDOM().hasClass(getDOM().querySelector(fixture.nativeElement, 'span'), 'foo'))
|
||||
.toBe(true);
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -33,11 +33,10 @@ export function main() {
|
||||
});
|
||||
|
||||
it('should display the template according to the exact value', async(() => {
|
||||
const template = '<div>' +
|
||||
'<ul [ngPlural]="switchValue">' +
|
||||
const template = '<ul [ngPlural]="switchValue">' +
|
||||
'<template ngPluralCase="=0"><li>you have no messages.</li></template>' +
|
||||
'<template ngPluralCase="=1"><li>you have one message.</li></template>' +
|
||||
'</ul></div>';
|
||||
'</ul>';
|
||||
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
@ -51,10 +50,9 @@ export function main() {
|
||||
// https://github.com/angular/angular/issues/9868
|
||||
// https://github.com/angular/angular/issues/9882
|
||||
it('should not throw when ngPluralCase contains expressions', async(() => {
|
||||
const template = '<div>' +
|
||||
'<ul [ngPlural]="switchValue">' +
|
||||
const template = '<ul [ngPlural]="switchValue">' +
|
||||
'<template ngPluralCase="=0"><li>{{ switchValue }}</li></template>' +
|
||||
'</ul></div>';
|
||||
'</ul>';
|
||||
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
@ -64,11 +62,10 @@ export function main() {
|
||||
|
||||
|
||||
it('should be applicable to <ng-container> elements', async(() => {
|
||||
const template = '<div>' +
|
||||
'<ng-container [ngPlural]="switchValue">' +
|
||||
const template = '<ng-container [ngPlural]="switchValue">' +
|
||||
'<template ngPluralCase="=0">you have no messages.</template>' +
|
||||
'<template ngPluralCase="=1">you have one message.</template>' +
|
||||
'</ng-container></div>';
|
||||
'</ng-container>';
|
||||
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
@ -80,11 +77,10 @@ export function main() {
|
||||
}));
|
||||
|
||||
it('should display the template according to the category', async(() => {
|
||||
const template = '<div>' +
|
||||
'<ul [ngPlural]="switchValue">' +
|
||||
const template = '<ul [ngPlural]="switchValue">' +
|
||||
'<template ngPluralCase="few"><li>you have a few messages.</li></template>' +
|
||||
'<template ngPluralCase="many"><li>you have many messages.</li></template>' +
|
||||
'</ul></div>';
|
||||
'</ul>';
|
||||
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
@ -96,11 +92,10 @@ export function main() {
|
||||
}));
|
||||
|
||||
it('should default to other when no matches are found', async(() => {
|
||||
const template = '<div>' +
|
||||
'<ul [ngPlural]="switchValue">' +
|
||||
const template = '<ul [ngPlural]="switchValue">' +
|
||||
'<template ngPluralCase="few"><li>you have a few messages.</li></template>' +
|
||||
'<template ngPluralCase="other"><li>default message.</li></template>' +
|
||||
'</ul></div>';
|
||||
'</ul>';
|
||||
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
@ -109,11 +104,10 @@ export function main() {
|
||||
}));
|
||||
|
||||
it('should prioritize value matches over category matches', async(() => {
|
||||
const template = '<div>' +
|
||||
'<ul [ngPlural]="switchValue">' +
|
||||
const template = '<ul [ngPlural]="switchValue">' +
|
||||
'<template ngPluralCase="few"><li>you have a few messages.</li></template>' +
|
||||
'<template ngPluralCase="=2">you have two messages.</template>' +
|
||||
'</ul></div>';
|
||||
'</ul>';
|
||||
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
|
@ -29,22 +29,19 @@ export function main() {
|
||||
it('should add styles specified in an object literal', async(() => {
|
||||
const template = `<div [ngStyle]="{'max-width': '40px'}"></div>`;
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
fixture.detectChanges();
|
||||
expectNativeEl(fixture).toHaveCssStyle({'max-width': '40px'});
|
||||
}));
|
||||
|
||||
it('should add and change styles specified in an object expression', async(() => {
|
||||
const template = `<div [ngStyle]="expr"></div>`;
|
||||
|
||||
fixture = createTestComponent(template);
|
||||
let expr: {[k: string]: string};
|
||||
|
||||
getComponent().expr = {'max-width': '40px'};
|
||||
fixture.detectChanges();
|
||||
expectNativeEl(fixture).toHaveCssStyle({'max-width': '40px'});
|
||||
|
||||
expr = getComponent().expr;
|
||||
let expr = getComponent().expr;
|
||||
expr['max-width'] = '30%';
|
||||
fixture.detectChanges();
|
||||
expectNativeEl(fixture).toHaveCssStyle({'max-width': '30%'});
|
||||
|
@ -33,11 +33,10 @@ export function main() {
|
||||
|
||||
describe('switch value changes', () => {
|
||||
it('should switch amongst when values', () => {
|
||||
const template = '<div>' +
|
||||
'<ul [ngSwitch]="switchValue">' +
|
||||
'<template ngSwitchCase="a"><li>when a</li></template>' +
|
||||
'<template ngSwitchCase="b"><li>when b</li></template>' +
|
||||
'</ul></div>';
|
||||
const template = '<ul [ngSwitch]="switchValue">' +
|
||||
'<li *ngSwitchCase="\'a\'">when a</li>' +
|
||||
'<li *ngSwitchCase="\'b\'">when b</li>' +
|
||||
'</ul>';
|
||||
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
@ -51,11 +50,10 @@ export function main() {
|
||||
});
|
||||
|
||||
it('should switch amongst when values with fallback to default', () => {
|
||||
const template = '<div>' +
|
||||
'<ul [ngSwitch]="switchValue">' +
|
||||
'<li template="ngSwitchCase \'a\'">when a</li>' +
|
||||
'<li template="ngSwitchDefault">when default</li>' +
|
||||
'</ul></div>';
|
||||
const template = '<ul [ngSwitch]="switchValue">' +
|
||||
'<li *ngSwitchCase="\'a\'">when a</li>' +
|
||||
'<li *ngSwitchDefault>when default</li>' +
|
||||
'</ul>';
|
||||
|
||||
fixture = createTestComponent(template);
|
||||
detectChangesAndExpectText('when default');
|
||||
@ -71,15 +69,14 @@ export function main() {
|
||||
});
|
||||
|
||||
it('should support multiple whens with the same value', () => {
|
||||
const template = '<div>' +
|
||||
'<ul [ngSwitch]="switchValue">' +
|
||||
'<template ngSwitchCase="a"><li>when a1;</li></template>' +
|
||||
'<template ngSwitchCase="b"><li>when b1;</li></template>' +
|
||||
'<template ngSwitchCase="a"><li>when a2;</li></template>' +
|
||||
'<template ngSwitchCase="b"><li>when b2;</li></template>' +
|
||||
'<template ngSwitchDefault><li>when default1;</li></template>' +
|
||||
'<template ngSwitchDefault><li>when default2;</li></template>' +
|
||||
'</ul></div>';
|
||||
const template = '<ul [ngSwitch]="switchValue">' +
|
||||
'<li *ngSwitchCase="\'a\'">when a1;</li>' +
|
||||
'<li *ngSwitchCase="\'b\'">when b1;</li>' +
|
||||
'<li *ngSwitchCase="\'a\'">when a2;</li>' +
|
||||
'<li *ngSwitchCase="\'b\'">when b2;</li>' +
|
||||
'<li *ngSwitchDefault>when default1;</li>' +
|
||||
'<li *ngSwitchDefault>when default2;</li>' +
|
||||
'</ul>';
|
||||
|
||||
fixture = createTestComponent(template);
|
||||
detectChangesAndExpectText('when default1;when default2;');
|
||||
@ -94,12 +91,11 @@ export function main() {
|
||||
|
||||
describe('when values changes', () => {
|
||||
it('should switch amongst when values', () => {
|
||||
const template = '<div>' +
|
||||
'<ul [ngSwitch]="switchValue">' +
|
||||
'<template [ngSwitchCase]="when1"><li>when 1;</li></template>' +
|
||||
'<template [ngSwitchCase]="when2"><li>when 2;</li></template>' +
|
||||
'<template ngSwitchDefault><li>when default;</li></template>' +
|
||||
'</ul></div>';
|
||||
const template = '<ul [ngSwitch]="switchValue">' +
|
||||
'<li *ngSwitchCase="when1">when 1;</li>' +
|
||||
'<li *ngSwitchCase="when2">when 2;</li>' +
|
||||
'<li *ngSwitchDefault>when default;</li>' +
|
||||
'</ul>';
|
||||
|
||||
fixture = createTestComponent(template);
|
||||
getComponent().when1 = 'a';
|
||||
@ -148,11 +144,10 @@ export function main() {
|
||||
});
|
||||
|
||||
it('should create the default case if there is no other case', () => {
|
||||
const template = '<div>' +
|
||||
'<ul [ngSwitch]="switchValue">' +
|
||||
'<template ngSwitchDefault><li>when default1;</li></template>' +
|
||||
'<template ngSwitchDefault><li>when default2;</li></template>' +
|
||||
'</ul></div>';
|
||||
const template = '<ul [ngSwitch]="switchValue">' +
|
||||
'<li *ngSwitchDefault>when default1;</li>' +
|
||||
'<li *ngSwitchDefault>when default2;</li>' +
|
||||
'</ul>';
|
||||
|
||||
fixture = createTestComponent(template);
|
||||
detectChangesAndExpectText('when default1;when default2;');
|
||||
@ -160,15 +155,14 @@ export function main() {
|
||||
});
|
||||
|
||||
it('should allow defaults before cases', () => {
|
||||
const template = '<div>' +
|
||||
'<ul [ngSwitch]="switchValue">' +
|
||||
'<template ngSwitchDefault><li>when default1;</li></template>' +
|
||||
'<template ngSwitchDefault><li>when default2;</li></template>' +
|
||||
'<template ngSwitchCase="a"><li>when a1;</li></template>' +
|
||||
'<template ngSwitchCase="b"><li>when b1;</li></template>' +
|
||||
'<template ngSwitchCase="a"><li>when a2;</li></template>' +
|
||||
'<template ngSwitchCase="b"><li>when b2;</li></template>' +
|
||||
'</ul></div>';
|
||||
const template = '<ul [ngSwitch]="switchValue">' +
|
||||
'<li *ngSwitchDefault>when default1;</li>' +
|
||||
'<li *ngSwitchDefault>when default2;</li>' +
|
||||
'<li *ngSwitchCase="\'a\'">when a1;</li>' +
|
||||
'<li *ngSwitchCase="\'b\'">when b1;</li>' +
|
||||
'<li *ngSwitchCase="\'a\'">when a2;</li>' +
|
||||
'<li *ngSwitchCase="\'b\'">when b2;</li>' +
|
||||
'</ul>';
|
||||
|
||||
fixture = createTestComponent(template);
|
||||
detectChangesAndExpectText('when default1;when default2;');
|
||||
|
@ -34,29 +34,22 @@ export function main() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should do nothing if templateRef is null', async(() => {
|
||||
const template = `<template [ngTemplateOutlet]="null"></template>`;
|
||||
it('should do nothing if templateRef is `null`', async(() => {
|
||||
const template = `<ng-container [ngTemplateOutlet]="null"></ng-container>`;
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
detectChangesAndExpectText('');
|
||||
}));
|
||||
|
||||
it('should insert content specified by TemplateRef', async(() => {
|
||||
const template =
|
||||
`<tpl-refs #refs="tplRefs"><template>foo</template></tpl-refs><template [ngTemplateOutlet]="currentTplRef"></template>`;
|
||||
const template = `<template #tpl>foo</template>` +
|
||||
`<ng-container [ngTemplateOutlet]="tpl"></ng-container>`;
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
detectChangesAndExpectText('');
|
||||
|
||||
const refs = fixture.debugElement.children[0].references['refs'];
|
||||
|
||||
setTplRef(refs.tplRefs.first);
|
||||
detectChangesAndExpectText('foo');
|
||||
}));
|
||||
|
||||
it('should clear content if TemplateRef becomes null', async(() => {
|
||||
const template =
|
||||
`<tpl-refs #refs="tplRefs"><template>foo</template></tpl-refs><template [ngTemplateOutlet]="currentTplRef"></template>`;
|
||||
it('should clear content if TemplateRef becomes `null`', async(() => {
|
||||
const template = `<tpl-refs #refs="tplRefs"><template>foo</template></tpl-refs>` +
|
||||
`<ng-container [ngTemplateOutlet]="currentTplRef"></ng-container>`;
|
||||
fixture = createTestComponent(template);
|
||||
fixture.detectChanges();
|
||||
const refs = fixture.debugElement.children[0].references['refs'];
|
||||
@ -70,7 +63,8 @@ export function main() {
|
||||
|
||||
it('should swap content if TemplateRef changes', async(() => {
|
||||
const template =
|
||||
`<tpl-refs #refs="tplRefs"><template>foo</template><template>bar</template></tpl-refs><template [ngTemplateOutlet]="currentTplRef"></template>`;
|
||||
`<tpl-refs #refs="tplRefs"><template>foo</template><template>bar</template></tpl-refs>` +
|
||||
`<ng-container [ngTemplateOutlet]="currentTplRef"></ng-container>`;
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
fixture.detectChanges();
|
||||
@ -83,70 +77,47 @@ export function main() {
|
||||
detectChangesAndExpectText('bar');
|
||||
}));
|
||||
|
||||
it('should display template if context is null', async(() => {
|
||||
const template =
|
||||
`<tpl-refs #refs="tplRefs"><template>foo</template></tpl-refs><template [ngTemplateOutlet]="currentTplRef" [ngOutletContext]="null"></template>`;
|
||||
it('should display template if context is `null`', async(() => {
|
||||
const template = `<template #tpl>foo</template>` +
|
||||
`<ng-container [ngTemplateOutlet]="tpl" [ngOutletContext]="null"></ng-container>`;
|
||||
fixture = createTestComponent(template);
|
||||
detectChangesAndExpectText('');
|
||||
|
||||
const refs = fixture.debugElement.children[0].references['refs'];
|
||||
|
||||
setTplRef(refs.tplRefs.first);
|
||||
detectChangesAndExpectText('foo');
|
||||
}));
|
||||
|
||||
it('should reflect initial context and changes', async(() => {
|
||||
const template =
|
||||
`<tpl-refs #refs="tplRefs"><template let-foo="foo"><span>{{foo}}</span></template></tpl-refs><template [ngTemplateOutlet]="currentTplRef" [ngOutletContext]="context"></template>`;
|
||||
const template = `<template let-foo="foo" #tpl>{{foo}}</template>` +
|
||||
`<ng-container [ngTemplateOutlet]="tpl" [ngOutletContext]="context"></ng-container>`;
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
const refs = fixture.debugElement.children[0].references['refs'];
|
||||
setTplRef(refs.tplRefs.first);
|
||||
|
||||
detectChangesAndExpectText('bar');
|
||||
|
||||
fixture.componentInstance.context.foo = 'alter-bar';
|
||||
|
||||
detectChangesAndExpectText('alter-bar');
|
||||
}));
|
||||
|
||||
it('should reflect user defined $implicit property in the context', async(() => {
|
||||
const template =
|
||||
`<tpl-refs #refs="tplRefs"><template let-ctx><span>{{ctx.foo}}</span></template></tpl-refs><template [ngTemplateOutlet]="currentTplRef" [ngOutletContext]="context"></template>`;
|
||||
it('should reflect user defined `$implicit` property in the context', async(() => {
|
||||
const template = `<template let-ctx #tpl>{{ctx.foo}}</template>` +
|
||||
`<ng-container [ngTemplateOutlet]="tpl" [ngOutletContext]="context"></ng-container>`;
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
const refs = fixture.debugElement.children[0].references['refs'];
|
||||
setTplRef(refs.tplRefs.first);
|
||||
|
||||
fixture.componentInstance.context = {$implicit: fixture.componentInstance.context};
|
||||
detectChangesAndExpectText('bar');
|
||||
fixture.componentInstance.context = {$implicit: {foo: 'bra'}};
|
||||
detectChangesAndExpectText('bra');
|
||||
}));
|
||||
|
||||
it('should reflect context re-binding', async(() => {
|
||||
const template =
|
||||
`<tpl-refs #refs="tplRefs"><template let-shawshank="shawshank"><span>{{shawshank}}</span></template></tpl-refs><template [ngTemplateOutlet]="currentTplRef" [ngOutletContext]="context"></template>`;
|
||||
const template = `<template let-shawshank="shawshank" #tpl>{{shawshank}}</template>` +
|
||||
`<ng-container [ngTemplateOutlet]="tpl" [ngOutletContext]="context"></ng-container>`;
|
||||
fixture = createTestComponent(template);
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
const refs = fixture.debugElement.children[0].references['refs'];
|
||||
setTplRef(refs.tplRefs.first);
|
||||
fixture.componentInstance.context = {shawshank: 'brooks'};
|
||||
|
||||
detectChangesAndExpectText('brooks');
|
||||
|
||||
fixture.componentInstance.context = {shawshank: 'was here'};
|
||||
|
||||
detectChangesAndExpectText('was here');
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Directive({selector: 'tpl-refs', exportAs: 'tplRefs'})
|
||||
class CaptureTplRefs {
|
||||
@ContentChildren(TemplateRef) tplRefs: QueryList<TemplateRef<any>>;
|
||||
@ -162,4 +133,4 @@ function createTestComponent(template: string): ComponentFixture<TestComponent>
|
||||
return TestBed.overrideComponent(TestComponent, {set: {template: template}})
|
||||
.configureTestingModule({schemas: [NO_ERRORS_SCHEMA]})
|
||||
.createComponent(TestComponent);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Component, NgModule} from '@angular/core';
|
||||
import {RouterModule} from '@angular/router';
|
||||
|
||||
@Component({selector: 'lazy-feature-comp', template: 'lazy feature, nested!'})
|
||||
export class LazyFeatureNestedComponent {
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild([
|
||||
{path: '', component: LazyFeatureNestedComponent, pathMatch: 'full'},
|
||||
])],
|
||||
declarations: [LazyFeatureNestedComponent]
|
||||
})
|
||||
export class LazyFeatureNestedModule {
|
||||
}
|
@ -16,7 +16,10 @@ export class LazyFeatureComponent {
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild([
|
||||
{path: '', component: LazyFeatureComponent, pathMatch: 'full'},
|
||||
{path: 'feature', loadChildren: './feature.module#FeatureModule'}
|
||||
{path: 'feature', loadChildren: './feature.module#FeatureModule'}, {
|
||||
path: 'nested-feature',
|
||||
loadChildren: './lazy-feature-nested.module#LazyFeatureNestedModule'
|
||||
}
|
||||
])],
|
||||
declarations: [LazyFeatureComponent]
|
||||
})
|
||||
|
@ -191,6 +191,8 @@ function lazyRoutesTest() {
|
||||
'./lazy.module#LazyModule': 'lazy.module.ts',
|
||||
'./feature/feature.module#FeatureModule': 'feature/feature.module.ts',
|
||||
'./feature/lazy-feature.module#LazyFeatureModule': 'feature/lazy-feature.module.ts',
|
||||
'./feature.module#FeatureModule': 'feature/feature.module.ts',
|
||||
'./lazy-feature-nested.module#LazyFeatureNestedModule': 'feature/lazy-feature-nested.module.ts',
|
||||
'feature2/feature2.module#Feature2Module': 'feature2/feature2.module.ts',
|
||||
'./default.module': 'feature2/default.module.ts',
|
||||
'feature/feature.module#FeatureModule': 'feature/feature.module.ts'
|
||||
|
@ -9,7 +9,7 @@
|
||||
"ng-xi18n": "./src/extract_i18n.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/tsc-wrapped": "0.5.0",
|
||||
"@angular/tsc-wrapped": "0.5.1",
|
||||
"reflect-metadata": "^0.1.2",
|
||||
"minimist": "^1.2.0"
|
||||
},
|
||||
|
@ -15,8 +15,6 @@
|
||||
import {AotCompilerHost, StaticReflector, StaticSymbol} from '@angular/compiler';
|
||||
import {NgModule} from '@angular/core';
|
||||
|
||||
|
||||
|
||||
// We cannot depend directly to @angular/router.
|
||||
type Route = any;
|
||||
const ROUTER_MODULE_PATH = '@angular/router/src/router_config_loader';
|
||||
@ -63,29 +61,37 @@ export function listLazyRoutesOfModule(
|
||||
const className = entryRouteDef.className;
|
||||
|
||||
// List loadChildren of this single module.
|
||||
const staticSymbol = reflector.findDeclaration(modulePath, className, containingFile);
|
||||
const appStaticSymbol = reflector.findDeclaration(modulePath, className, containingFile);
|
||||
const ROUTES = reflector.findDeclaration(ROUTER_MODULE_PATH, ROUTER_ROUTES_SYMBOL_NAME);
|
||||
const lazyRoutes: LazyRoute[] =
|
||||
_extractLazyRoutesFromStaticModule(staticSymbol, reflector, host, ROUTES);
|
||||
const routes: LazyRouteMap = {};
|
||||
_extractLazyRoutesFromStaticModule(appStaticSymbol, reflector, host, ROUTES);
|
||||
|
||||
lazyRoutes.forEach((lazyRoute: LazyRoute) => {
|
||||
const route: string = lazyRoute.routeDef.toString();
|
||||
_assertRoute(routes, lazyRoute);
|
||||
routes[route] = lazyRoute;
|
||||
const allLazyRoutes = lazyRoutes.reduce(
|
||||
function includeLazyRouteAndSubRoutes(allRoutes: LazyRouteMap, lazyRoute: LazyRoute):
|
||||
LazyRouteMap {
|
||||
const route: string = lazyRoute.routeDef.toString();
|
||||
_assertRoute(allRoutes, lazyRoute);
|
||||
allRoutes[route] = lazyRoute;
|
||||
|
||||
const lazyModuleSymbol = reflector.findDeclaration(
|
||||
lazyRoute.absoluteFilePath, lazyRoute.routeDef.className || 'default');
|
||||
const subRoutes = _extractLazyRoutesFromStaticModule(lazyModuleSymbol, reflector, host, ROUTES);
|
||||
// StaticReflector does not support discovering annotations like `NgModule` on default
|
||||
// exports
|
||||
// Which means: if a default export NgModule was lazy-loaded, we can discover it, but,
|
||||
// we cannot parse its routes to see if they have loadChildren or not.
|
||||
if (!lazyRoute.routeDef.className) {
|
||||
return allRoutes;
|
||||
}
|
||||
|
||||
// Populate the map using the routes we just found.
|
||||
subRoutes.forEach(subRoute => {
|
||||
_assertRoute(routes, subRoute);
|
||||
routes[subRoute.routeDef.toString()] = subRoute;
|
||||
});
|
||||
});
|
||||
const lazyModuleSymbol = reflector.findDeclaration(
|
||||
lazyRoute.absoluteFilePath, lazyRoute.routeDef.className || 'default');
|
||||
|
||||
return routes;
|
||||
const subRoutes =
|
||||
_extractLazyRoutesFromStaticModule(lazyModuleSymbol, reflector, host, ROUTES);
|
||||
|
||||
return subRoutes.reduce(includeLazyRouteAndSubRoutes, allRoutes);
|
||||
},
|
||||
{});
|
||||
|
||||
return allLazyRoutes;
|
||||
}
|
||||
|
||||
|
||||
@ -192,7 +198,7 @@ function _collectRoutes(
|
||||
*/
|
||||
function _collectLoadChildren(routes: Route[]): string[] {
|
||||
return routes.reduce((m, r) => {
|
||||
if (r.loadChildren) {
|
||||
if (r.loadChildren && typeof r.loadChildren === 'string') {
|
||||
return m.concat(r.loadChildren);
|
||||
} else if (Array.isArray(r)) {
|
||||
return m.concat(_collectLoadChildren(r));
|
||||
|
@ -6,8 +6,6 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {SchemaMetadata} from '@angular/core';
|
||||
|
||||
import {AnimationCompiler} from '../animation/animation_compiler';
|
||||
import {AnimationParser} from '../animation/animation_parser';
|
||||
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompilePipeMetadata, CompileProviderMetadata, CompileTypeSummary, createHostComponentMeta, identifierModuleUrl, identifierName} from '../compile_metadata';
|
||||
|
@ -10,8 +10,8 @@ import {Attribute, Component, ContentChild, ContentChildren, Directive, Host, Ho
|
||||
|
||||
import {ReflectorReader} from '../private_import_core';
|
||||
|
||||
import {StaticSymbol, StaticSymbolCache} from './static_symbol';
|
||||
import {ResolvedStaticSymbol, StaticSymbolResolver} from './static_symbol_resolver';
|
||||
import {StaticSymbol} from './static_symbol';
|
||||
import {StaticSymbolResolver} from './static_symbol_resolver';
|
||||
|
||||
const ANGULAR_IMPORT_LOCATIONS = {
|
||||
coreDecorators: '@angular/core/src/metadata',
|
||||
@ -310,6 +310,7 @@ export class StaticReflector implements ReflectorReader {
|
||||
if (value && (depth != 0 || value.__symbolic != 'error')) {
|
||||
const parameters: string[] = targetFunction['parameters'];
|
||||
const defaults: any[] = targetFunction.defaults;
|
||||
args = args.map(arg => simplifyInContext(context, arg, depth + 1));
|
||||
if (defaults && defaults.length > args.length) {
|
||||
args.push(...defaults.slice(args.length).map((value: any) => simplify(value)));
|
||||
}
|
||||
@ -499,15 +500,15 @@ export class StaticReflector implements ReflectorReader {
|
||||
return context;
|
||||
}
|
||||
const argExpressions: any[] = expression['arguments'] || [];
|
||||
const args =
|
||||
argExpressions.map(arg => simplifyInContext(context, arg, depth + 1));
|
||||
let converter = self.conversionMap.get(staticSymbol);
|
||||
if (converter) {
|
||||
const args =
|
||||
argExpressions.map(arg => simplifyInContext(context, arg, depth + 1));
|
||||
return converter(context, args);
|
||||
} else {
|
||||
// Determine if the function is one we can simplify.
|
||||
const targetFunction = resolveReferenceValue(staticSymbol);
|
||||
return simplifyCall(staticSymbol, targetFunction, args);
|
||||
return simplifyCall(staticSymbol, targetFunction, argExpressions);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -651,10 +652,6 @@ class PopulatedScope extends BindingScope {
|
||||
}
|
||||
}
|
||||
|
||||
function sameSymbol(a: StaticSymbol, b: StaticSymbol): boolean {
|
||||
return a === b;
|
||||
}
|
||||
|
||||
function shouldIgnore(value: any): boolean {
|
||||
return value && value.__symbolic == 'ignore';
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import {CompileSummaryKind, CompileTypeSummary} from '../compile_metadata';
|
||||
|
||||
import {Summary, SummaryResolver} from '../summary_resolver';
|
||||
|
||||
import {StaticSymbol, StaticSymbolCache} from './static_symbol';
|
||||
|
@ -5,16 +5,16 @@
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import {CompileDirectiveSummary, CompileIdentifierMetadata, CompileNgModuleSummary, CompilePipeSummary, CompileSummaryKind, CompileTypeMetadata, CompileTypeSummary, identifierModuleUrl, identifierName} from '../compile_metadata';
|
||||
import {CompileNgModuleSummary, CompileSummaryKind, CompileTypeSummary} from '../compile_metadata';
|
||||
import {Summary, SummaryResolver} from '../summary_resolver';
|
||||
import {ValueTransformer, visitValue} from '../util';
|
||||
|
||||
import {GeneratedFile} from './generated_file';
|
||||
import {StaticSymbol, StaticSymbolCache} from './static_symbol';
|
||||
import {ResolvedStaticSymbol, StaticSymbolResolver} from './static_symbol_resolver';
|
||||
|
||||
const STRIP_SRC_FILE_SUFFIXES = /(\.ts|\.d\.ts|\.js|\.jsx|\.tsx)$/;
|
||||
|
||||
|
||||
export interface AotSummarySerializerHost {
|
||||
/**
|
||||
* Returns the output file path of a source file.
|
||||
@ -180,4 +180,4 @@ class Deserializer extends ValueTransformer {
|
||||
return super.visitStringMap(map, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,6 @@
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Identifiers, createIdentifier} from '../identifiers';
|
||||
import {ClassBuilder} from '../output/class_builder';
|
||||
import * as o from '../output/output_ast';
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
|
||||
import * as cdAst from '../expression_parser/ast';
|
||||
import {isBlank, isPresent} from '../facade/lang';
|
||||
import {isBlank} from '../facade/lang';
|
||||
import {Identifiers, createIdentifier} from '../identifiers';
|
||||
import {ClassBuilder} from '../output/class_builder';
|
||||
import * as o from '../output/output_ast';
|
||||
@ -338,7 +338,7 @@ class _AstToIrVisitor implements cdAst.AstVisitor {
|
||||
const receiver = this.visit(ast.receiver, _Mode.Expression);
|
||||
if (receiver === this._implicitReceiver) {
|
||||
const varExpr = this._getLocal(ast.name);
|
||||
if (isPresent(varExpr)) {
|
||||
if (varExpr) {
|
||||
result = varExpr.callFn(args);
|
||||
}
|
||||
}
|
||||
@ -374,7 +374,7 @@ class _AstToIrVisitor implements cdAst.AstVisitor {
|
||||
const receiver: o.Expression = this.visit(ast.receiver, _Mode.Expression);
|
||||
if (receiver === this._implicitReceiver) {
|
||||
const varExpr = this._getLocal(ast.name);
|
||||
if (isPresent(varExpr)) {
|
||||
if (varExpr) {
|
||||
throw new Error('Cannot assign to a reference or variable!');
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
import {Component, ViewEncapsulation} from '@angular/core';
|
||||
|
||||
import {CompileAnimationEntryMetadata, CompileDirectiveMetadata, CompileStylesheetMetadata, CompileTemplateMetadata, CompileTypeMetadata} from './compile_metadata';
|
||||
import {CompileAnimationEntryMetadata, CompileDirectiveMetadata, CompileStylesheetMetadata, CompileTemplateMetadata} from './compile_metadata';
|
||||
import {CompilerConfig} from './config';
|
||||
import {isBlank, isPresent, stringify} from './facade/lang';
|
||||
import {CompilerInjectable} from './injectable';
|
||||
|
@ -14,8 +14,6 @@ import {CompilerInjectable} from './injectable';
|
||||
import {ReflectorReader, reflector} from './private_import_core';
|
||||
import {splitAtColon} from './util';
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Resolve a `Type` for {@link Directive}.
|
||||
*
|
||||
|
@ -128,7 +128,6 @@ class DirectiveWrapperBuilder implements ClassBuilder {
|
||||
new o.ClassMethod('ngOnDestroy', [], this.destroyStmts),
|
||||
];
|
||||
|
||||
|
||||
const fields: o.ClassField[] = [
|
||||
new o.ClassField(EVENT_HANDLER_FIELD_NAME, o.FUNCTION_TYPE, [o.StmtModifier.Private]),
|
||||
new o.ClassField(CONTEXT_FIELD_NAME, o.importType(this.dirMeta.type)),
|
||||
|
@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import * as chars from '../chars';
|
||||
import {NumberWrapper, isPresent} from '../facade/lang';
|
||||
import {NumberWrapper} from '../facade/lang';
|
||||
import {CompilerInjectable} from '../injectable';
|
||||
|
||||
export enum TokenType {
|
||||
@ -241,7 +241,7 @@ class _Scanner {
|
||||
this.advance();
|
||||
str += two;
|
||||
}
|
||||
if (isPresent(threeCode) && this.peek == threeCode) {
|
||||
if (threeCode != null && this.peek == threeCode) {
|
||||
this.advance();
|
||||
str += three;
|
||||
}
|
||||
|
@ -53,20 +53,22 @@ enum _VisitorMode {
|
||||
* @internal
|
||||
*/
|
||||
class _Visitor implements html.Visitor {
|
||||
private _depth: number;
|
||||
|
||||
// <el i18n>...</el>
|
||||
private _inI18nNode: boolean;
|
||||
private _depth: number;
|
||||
private _inImplicitNode: boolean;
|
||||
|
||||
// <!--i18n-->...<!--/i18n-->
|
||||
private _inI18nBlock: boolean;
|
||||
private _blockMeaningAndDesc: string;
|
||||
private _blockChildren: html.Node[];
|
||||
private _blockStartDepth: number;
|
||||
private _inI18nBlock: boolean;
|
||||
|
||||
// {<icu message>}
|
||||
private _inIcu: boolean;
|
||||
|
||||
// set to void 0 when not in a section
|
||||
private _msgCountAtSectionStart: number;
|
||||
private _errors: I18nError[];
|
||||
private _mode: _VisitorMode;
|
||||
@ -208,50 +210,31 @@ class _Visitor implements html.Visitor {
|
||||
this._depth++;
|
||||
const wasInI18nNode = this._inI18nNode;
|
||||
const wasInImplicitNode = this._inImplicitNode;
|
||||
let childNodes: html.Node[];
|
||||
let childNodes: html.Node[] = [];
|
||||
let translatedChildNodes: html.Node[];
|
||||
|
||||
// Extract only top level nodes with the (implicit) "i18n" attribute if not in a block or an ICU
|
||||
// message
|
||||
// Extract:
|
||||
// - top level nodes with the (implicit) "i18n" attribute if not already in a section
|
||||
// - ICU messages
|
||||
const i18nAttr = _getI18nAttr(el);
|
||||
const i18nMeta = i18nAttr ? i18nAttr.value : '';
|
||||
const isImplicit = this._implicitTags.some(tag => el.name === tag) && !this._inIcu &&
|
||||
!this._isInTranslatableSection;
|
||||
const isTopLevelImplicit = !wasInImplicitNode && isImplicit;
|
||||
this._inImplicitNode = this._inImplicitNode || isImplicit;
|
||||
this._inImplicitNode = wasInImplicitNode || isImplicit;
|
||||
|
||||
if (!this._isInTranslatableSection && !this._inIcu) {
|
||||
if (i18nAttr) {
|
||||
// explicit translation
|
||||
if (i18nAttr || isTopLevelImplicit) {
|
||||
this._inI18nNode = true;
|
||||
const message = this._addMessage(el.children, i18nAttr.value);
|
||||
childNodes = this._translateMessage(el, message);
|
||||
} else if (isTopLevelImplicit) {
|
||||
// implicit translation
|
||||
this._inI18nNode = true;
|
||||
const message = this._addMessage(el.children);
|
||||
childNodes = this._translateMessage(el, message);
|
||||
const message = this._addMessage(el.children, i18nMeta);
|
||||
translatedChildNodes = this._translateMessage(el, message);
|
||||
}
|
||||
|
||||
if (this._mode == _VisitorMode.Extract) {
|
||||
const isTranslatable = i18nAttr || isTopLevelImplicit;
|
||||
if (isTranslatable) {
|
||||
this._openTranslatableSection(el);
|
||||
}
|
||||
if (isTranslatable) this._openTranslatableSection(el);
|
||||
html.visitAll(this, el.children);
|
||||
if (isTranslatable) {
|
||||
this._closeTranslatableSection(el, el.children);
|
||||
}
|
||||
}
|
||||
|
||||
if (this._mode === _VisitorMode.Merge && !i18nAttr && !isTopLevelImplicit) {
|
||||
childNodes = [];
|
||||
el.children.forEach(child => {
|
||||
const visited = child.visit(this, context);
|
||||
if (visited && !this._isInTranslatableSection) {
|
||||
// Do not add the children from translatable sections (= i18n blocks here)
|
||||
// They will be added when the section is close (i.e. on `<!-- /i18n -->`)
|
||||
childNodes = childNodes.concat(visited);
|
||||
}
|
||||
});
|
||||
if (isTranslatable) this._closeTranslatableSection(el, el.children);
|
||||
}
|
||||
} else {
|
||||
if (i18nAttr || isTopLevelImplicit) {
|
||||
@ -263,19 +246,18 @@ class _Visitor implements html.Visitor {
|
||||
// Descend into child nodes for extraction
|
||||
html.visitAll(this, el.children);
|
||||
}
|
||||
}
|
||||
|
||||
if (this._mode == _VisitorMode.Merge) {
|
||||
// Translate attributes in ICU messages
|
||||
childNodes = [];
|
||||
el.children.forEach(child => {
|
||||
const visited = child.visit(this, context);
|
||||
if (visited && !this._isInTranslatableSection) {
|
||||
// Do not add the children from translatable sections (= i18n blocks here)
|
||||
// They will be added when the section is close (i.e. on `<!-- /i18n -->`)
|
||||
childNodes = childNodes.concat(visited);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (this._mode === _VisitorMode.Merge) {
|
||||
const visitNodes = translatedChildNodes || el.children;
|
||||
visitNodes.forEach(child => {
|
||||
const visited = child.visit(this, context);
|
||||
if (visited && !this._isInTranslatableSection) {
|
||||
// Do not add the children from translatable sections (= i18n blocks here)
|
||||
// They will be added later in this loop when the block closes (i.e. on `<!-- /i18n -->`)
|
||||
childNodes = childNodes.concat(visited);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this._visitAttributesOf(el);
|
||||
@ -285,7 +267,6 @@ class _Visitor implements html.Visitor {
|
||||
this._inImplicitNode = wasInImplicitNode;
|
||||
|
||||
if (this._mode === _VisitorMode.Merge) {
|
||||
// There are no childNodes in translatable sections - those nodes will be replace anyway
|
||||
const translatedAttrs = this._translateAttributes(el);
|
||||
return new html.Element(
|
||||
el.name, translatedAttrs, childNodes, el.sourceSpan, el.startSourceSpan,
|
||||
@ -432,7 +413,7 @@ class _Visitor implements html.Visitor {
|
||||
|
||||
/**
|
||||
* A translatable section could be:
|
||||
* - a translatable element,
|
||||
* - the content of translatable element,
|
||||
* - nodes between `<!-- i18n -->` and `<!-- /i18n -->` comments
|
||||
*/
|
||||
private get _isInTranslatableSection(): boolean {
|
||||
|
@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ANALYZE_FOR_ENTRY_COMPONENTS, AnimationTransitionEvent, ChangeDetectionStrategy, ChangeDetectorRef, ComponentFactory, ComponentFactoryResolver, ComponentRef, ElementRef, Injector, LOCALE_ID, NgModuleFactory, QueryList, RenderComponentType, Renderer, SecurityContext, SimpleChange, TRANSLATIONS_FORMAT, TemplateRef, ViewContainerRef, ViewEncapsulation} from '@angular/core';
|
||||
import {ANALYZE_FOR_ENTRY_COMPONENTS, ChangeDetectionStrategy, ChangeDetectorRef, ComponentFactory, ComponentFactoryResolver, ComponentRef, ElementRef, Injector, LOCALE_ID, NgModuleFactory, QueryList, RenderComponentType, Renderer, SecurityContext, SimpleChange, TRANSLATIONS_FORMAT, TemplateRef, ViewContainerRef, ViewEncapsulation} from '@angular/core';
|
||||
|
||||
import {StaticSymbol} from './aot/static_symbol';
|
||||
import {CompileIdentifierMetadata, CompileTokenMetadata, identifierModuleUrl, identifierName} from './compile_metadata';
|
||||
|
@ -283,7 +283,7 @@ class _TreeBuilder {
|
||||
const tagDef = this.getTagDefinition(el.name);
|
||||
const {parent, container} = this._getParentElementSkippingContainers();
|
||||
|
||||
if (isPresent(parent) && tagDef.requireExtraParent(parent.name)) {
|
||||
if (parent && tagDef.requireExtraParent(parent.name)) {
|
||||
const newParent = new html.Element(
|
||||
tagDef.parentToAdd, [], [], el.sourceSpan, el.startSourceSpan, el.endSourceSpan);
|
||||
this._insertBeforeContainer(parent, container, newParent);
|
||||
|
@ -9,7 +9,7 @@
|
||||
import {CompileDiDependencyMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompileProviderMetadata, CompileTokenMetadata, identifierModuleUrl, identifierName, tokenName, tokenReference} from './compile_metadata';
|
||||
import {createDiTokenExpression} from './compiler_util/identifier_util';
|
||||
import {isPresent} from './facade/lang';
|
||||
import {Identifiers, createIdentifier, createIdentifierToken, resolveIdentifier} from './identifiers';
|
||||
import {Identifiers, createIdentifier, resolveIdentifier} from './identifiers';
|
||||
import {CompilerInjectable} from './injectable';
|
||||
import {ClassBuilder, createClassStmt} from './output/class_builder';
|
||||
import * as o from './output/output_ast';
|
||||
|
@ -9,7 +9,7 @@
|
||||
import {NgModule, Type} from '@angular/core';
|
||||
|
||||
import {ListWrapper} from './facade/collection';
|
||||
import {isPresent, stringify} from './facade/lang';
|
||||
import {stringify} from './facade/lang';
|
||||
import {CompilerInjectable} from './injectable';
|
||||
import {ReflectorReader, reflector} from './private_import_core';
|
||||
|
||||
@ -30,7 +30,7 @@ export class NgModuleResolver {
|
||||
const ngModuleMeta: NgModule =
|
||||
ListWrapper.findLast(this._reflector.annotations(type), _isNgModuleMetadata);
|
||||
|
||||
if (isPresent(ngModuleMeta)) {
|
||||
if (ngModuleMeta) {
|
||||
return ngModuleMeta;
|
||||
} else {
|
||||
if (throwIfNotFound) {
|
||||
|
@ -7,7 +7,6 @@
|
||||
*/
|
||||
|
||||
|
||||
import {CompileIdentifierMetadata} from '../compile_metadata';
|
||||
import {ValueTransformer, visitValue} from '../util';
|
||||
|
||||
import * as o from './output_ast';
|
||||
|
@ -9,7 +9,7 @@
|
||||
import {Pipe, Type, resolveForwardRef} from '@angular/core';
|
||||
|
||||
import {ListWrapper} from './facade/collection';
|
||||
import {isPresent, stringify} from './facade/lang';
|
||||
import {stringify} from './facade/lang';
|
||||
import {CompilerInjectable} from './injectable';
|
||||
import {ReflectorReader, reflector} from './private_import_core';
|
||||
|
||||
@ -38,9 +38,9 @@ export class PipeResolver {
|
||||
*/
|
||||
resolve(type: Type<any>, throwIfNotFound = true): Pipe {
|
||||
const metas = this._reflector.annotations(resolveForwardRef(type));
|
||||
if (isPresent(metas)) {
|
||||
if (metas) {
|
||||
const annotation = ListWrapper.findLast(metas, _isPipeMetadata);
|
||||
if (isPresent(annotation)) {
|
||||
if (annotation) {
|
||||
return annotation;
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
import {CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileDirectiveSummary, CompileNgModuleMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTokenMetadata, CompileTypeMetadata, tokenName, tokenReference} from './compile_metadata';
|
||||
import {isBlank, isPresent} from './facade/lang';
|
||||
import {Identifiers, createIdentifierToken, resolveIdentifier} from './identifiers';
|
||||
import {Identifiers, resolveIdentifier} from './identifiers';
|
||||
import {ParseError, ParseSourceSpan} from './parse_util';
|
||||
import {AttrAst, DirectiveAst, ProviderAst, ProviderAstType, ReferenceAst} from './template_parser/template_ast';
|
||||
|
||||
@ -114,7 +114,7 @@ export class ProviderElementContext {
|
||||
let queries: CompileQueryMetadata[];
|
||||
while (currentEl !== null) {
|
||||
queries = currentEl._contentQueries.get(tokenReference(token));
|
||||
if (isPresent(queries)) {
|
||||
if (queries) {
|
||||
result.push(...queries.filter((query) => query.descendants || distance <= 1));
|
||||
}
|
||||
if (currentEl._directiveAsts.length > 0) {
|
||||
@ -123,7 +123,7 @@ export class ProviderElementContext {
|
||||
currentEl = currentEl._parent;
|
||||
}
|
||||
queries = this.viewContext.viewQueries.get(tokenReference(token));
|
||||
if (isPresent(queries)) {
|
||||
if (queries) {
|
||||
result.push(...queries);
|
||||
}
|
||||
return result;
|
||||
@ -143,7 +143,7 @@ export class ProviderElementContext {
|
||||
return null;
|
||||
}
|
||||
let transformedProviderAst = this._transformedProviders.get(tokenReference(token));
|
||||
if (isPresent(transformedProviderAst)) {
|
||||
if (transformedProviderAst) {
|
||||
return transformedProviderAst;
|
||||
}
|
||||
if (isPresent(this._seenProviders.get(tokenReference(token)))) {
|
||||
@ -165,11 +165,11 @@ export class ProviderElementContext {
|
||||
transformedUseExisting = null;
|
||||
transformedUseValue = existingDiDep.value;
|
||||
}
|
||||
} else if (isPresent(provider.useFactory)) {
|
||||
} else if (provider.useFactory) {
|
||||
const deps = provider.deps || provider.useFactory.diDeps;
|
||||
transformedDeps =
|
||||
deps.map((dep) => this._getDependency(resolvedProvider.providerType, dep, eager));
|
||||
} else if (isPresent(provider.useClass)) {
|
||||
} else if (provider.useClass) {
|
||||
const deps = provider.deps || provider.useClass.diDeps;
|
||||
transformedDeps =
|
||||
deps.map((dep) => this._getDependency(resolvedProvider.providerType, dep, eager));
|
||||
@ -235,7 +235,7 @@ export class ProviderElementContext {
|
||||
}
|
||||
} else {
|
||||
// check parent elements
|
||||
while (!result && isPresent(currElement._parent)) {
|
||||
while (!result && currElement._parent) {
|
||||
const prevElement = currElement;
|
||||
currElement = currElement._parent;
|
||||
if (prevElement._isViewRoot) {
|
||||
@ -301,7 +301,7 @@ export class NgModuleProviderAnalyzer {
|
||||
return null;
|
||||
}
|
||||
let transformedProviderAst = this._transformedProviders.get(tokenReference(token));
|
||||
if (isPresent(transformedProviderAst)) {
|
||||
if (transformedProviderAst) {
|
||||
return transformedProviderAst;
|
||||
}
|
||||
if (isPresent(this._seenProviders.get(tokenReference(token)))) {
|
||||
@ -324,11 +324,11 @@ export class NgModuleProviderAnalyzer {
|
||||
transformedUseExisting = null;
|
||||
transformedUseValue = existingDiDep.value;
|
||||
}
|
||||
} else if (isPresent(provider.useFactory)) {
|
||||
} else if (provider.useFactory) {
|
||||
const deps = provider.deps || provider.useFactory.diDeps;
|
||||
transformedDeps =
|
||||
deps.map((dep) => this._getDependency(dep, eager, resolvedProvider.sourceSpan));
|
||||
} else if (isPresent(provider.useClass)) {
|
||||
} else if (provider.useClass) {
|
||||
const deps = provider.deps || provider.useClass.diDeps;
|
||||
transformedDeps =
|
||||
deps.map((dep) => this._getDependency(dep, eager, resolvedProvider.sourceSpan));
|
||||
@ -454,7 +454,7 @@ function _resolveProviders(
|
||||
|
||||
function _getViewQueries(component: CompileDirectiveMetadata): Map<any, CompileQueryMetadata[]> {
|
||||
const viewQueries = new Map<any, CompileQueryMetadata[]>();
|
||||
if (isPresent(component.viewQueries)) {
|
||||
if (component.viewQueries) {
|
||||
component.viewQueries.forEach((query) => _addQueryToTokenMap(viewQueries, query));
|
||||
}
|
||||
return viewQueries;
|
||||
@ -464,7 +464,7 @@ function _getContentQueries(directives: CompileDirectiveSummary[]):
|
||||
Map<any, CompileQueryMetadata[]> {
|
||||
const contentQueries = new Map<any, CompileQueryMetadata[]>();
|
||||
directives.forEach(directive => {
|
||||
if (isPresent(directive.queries)) {
|
||||
if (directive.queries) {
|
||||
directive.queries.forEach((query) => _addQueryToTokenMap(contentQueries, query));
|
||||
}
|
||||
});
|
||||
|
@ -11,7 +11,6 @@ import {SecurityContext} from '@angular/core';
|
||||
import {CompileDirectiveSummary, CompilePipeSummary} from '../compile_metadata';
|
||||
import {ASTWithSource, BindingPipe, EmptyExpr, ParserError, RecursiveAstVisitor, TemplateBinding} from '../expression_parser/ast';
|
||||
import {Parser} from '../expression_parser/parser';
|
||||
import {isPresent} from '../facade/lang';
|
||||
import {InterpolationConfig} from '../ml_parser/interpolation_config';
|
||||
import {mergeNsAndName} from '../ml_parser/tags';
|
||||
import {ParseError, ParseErrorLevel, ParseSourceSpan} from '../parse_util';
|
||||
@ -111,14 +110,14 @@ export class BindingParser {
|
||||
}
|
||||
|
||||
parseInlineTemplateBinding(
|
||||
name: string, prefixToken: string, value: string, sourceSpan: ParseSourceSpan,
|
||||
prefixToken: string, value: string, sourceSpan: ParseSourceSpan,
|
||||
targetMatchableAttrs: string[][], targetProps: BoundProperty[], targetVars: VariableAst[]) {
|
||||
const bindings = this._parseTemplateBindings(prefixToken, value, sourceSpan);
|
||||
for (let i = 0; i < bindings.length; i++) {
|
||||
const binding = bindings[i];
|
||||
if (binding.keyIsVar) {
|
||||
targetVars.push(new VariableAst(binding.key, binding.name, sourceSpan));
|
||||
} else if (isPresent(binding.expression)) {
|
||||
} else if (binding.expression) {
|
||||
this._parsePropertyAst(
|
||||
binding.key, binding.expression, sourceSpan, targetMatchableAttrs, targetProps);
|
||||
} else {
|
||||
@ -136,7 +135,7 @@ export class BindingParser {
|
||||
const bindingsResult = this._exprParser.parseTemplateBindings(prefixToken, value, sourceInfo);
|
||||
this._reportExpressionParserErrors(bindingsResult.errors, sourceSpan);
|
||||
bindingsResult.templateBindings.forEach((binding) => {
|
||||
if (isPresent(binding.expression)) {
|
||||
if (binding.expression) {
|
||||
this._checkPipes(binding.expression, sourceSpan);
|
||||
}
|
||||
});
|
||||
@ -193,7 +192,7 @@ export class BindingParser {
|
||||
name: string, value: string, sourceSpan: ParseSourceSpan, targetMatchableAttrs: string[][],
|
||||
targetProps: BoundProperty[]): boolean {
|
||||
const expr = this.parseInterpolation(value, sourceSpan);
|
||||
if (isPresent(expr)) {
|
||||
if (expr) {
|
||||
this._parsePropertyAst(name, expr, sourceSpan, targetMatchableAttrs, targetProps);
|
||||
return true;
|
||||
}
|
||||
@ -374,7 +373,7 @@ export class BindingParser {
|
||||
}
|
||||
|
||||
private _checkPipes(ast: ASTWithSource, sourceSpan: ParseSourceSpan) {
|
||||
if (isPresent(ast)) {
|
||||
if (ast) {
|
||||
const collector = new PipeCollector();
|
||||
ast.visit(collector);
|
||||
collector.pipes.forEach((ast, pipeName) => {
|
||||
|
@ -276,7 +276,7 @@ class TemplateParseVisitor implements html.Visitor {
|
||||
templateBindingsSource = attr.value;
|
||||
} else if (normalizedName.startsWith(TEMPLATE_ATTR_PREFIX)) {
|
||||
templateBindingsSource = attr.value;
|
||||
prefixToken = normalizedName.substring(TEMPLATE_ATTR_PREFIX.length);
|
||||
prefixToken = normalizedName.substring(TEMPLATE_ATTR_PREFIX.length) + ':';
|
||||
}
|
||||
|
||||
const hasTemplateBinding = isPresent(templateBindingsSource);
|
||||
@ -288,7 +288,7 @@ class TemplateParseVisitor implements html.Visitor {
|
||||
}
|
||||
hasInlineTemplates = true;
|
||||
this._bindingParser.parseInlineTemplateBinding(
|
||||
attr.name, prefixToken, templateBindingsSource, attr.sourceSpan, templateMatchableAttrs,
|
||||
prefixToken, templateBindingsSource, attr.sourceSpan, templateMatchableAttrs,
|
||||
templateElementOrDirectiveProps, templateElementVars);
|
||||
}
|
||||
|
||||
@ -309,9 +309,11 @@ class TemplateParseVisitor implements html.Visitor {
|
||||
const elementProps: BoundElementPropertyAst[] =
|
||||
this._createElementPropertyAsts(element.name, elementOrDirectiveProps, directiveAsts);
|
||||
const isViewRoot = parent.isTemplateElement || hasInlineTemplates;
|
||||
|
||||
const providerContext = new ProviderElementContext(
|
||||
this.providerViewContext, parent.providerContext, isViewRoot, directiveAsts, attrs,
|
||||
references, element.sourceSpan);
|
||||
|
||||
const children = html.visitAll(
|
||||
preparsedElement.nonBindable ? NON_BINDABLE_VISITOR : this, element.children,
|
||||
ElementContext.create(
|
||||
|
@ -19,7 +19,7 @@ import {ProviderAst, ProviderAstType, ReferenceAst, TemplateAst} from '../templa
|
||||
import {CompileMethod} from './compile_method';
|
||||
import {CompileQuery, addQueryToTokenMap, createQueryList} from './compile_query';
|
||||
import {CompileView, CompileViewRootNode} from './compile_view';
|
||||
import {InjectMethodVars, ViewProperties} from './constants';
|
||||
import {InjectMethodVars} from './constants';
|
||||
import {ComponentFactoryDependency, DirectiveWrapperDependency} from './deps';
|
||||
import {getPropertyInView, injectFromViewParentInjector} from './util';
|
||||
|
||||
@ -195,7 +195,7 @@ export class CompileElement extends CompileNode {
|
||||
const propName =
|
||||
`_${tokenName(resolvedProvider.token)}_${this.nodeIndex}_${this.instances.size}`;
|
||||
const instance = createProviderProperty(
|
||||
propName, resolvedProvider, providerValueExpressions, resolvedProvider.multiProvider,
|
||||
propName, providerValueExpressions, resolvedProvider.multiProvider,
|
||||
resolvedProvider.eager, this);
|
||||
if (isDirectiveWrapper) {
|
||||
this.directiveWrapperInstance.set(tokenReference(resolvedProvider.token), instance);
|
||||
@ -289,7 +289,7 @@ export class CompileElement extends CompileNode {
|
||||
CompileQuery {
|
||||
const propName =
|
||||
`_query_${tokenName(queryMeta.selectors[0])}_${this.nodeIndex}_${this._queryCount++}`;
|
||||
const queryList = createQueryList(queryMeta, directiveInstance, propName, this.view);
|
||||
const queryList = createQueryList(propName, this.view);
|
||||
const query = new CompileQuery(queryMeta, queryList, directiveInstance, this.view);
|
||||
addQueryToTokenMap(this._queries, query);
|
||||
return query;
|
||||
@ -369,8 +369,8 @@ function createInjectInternalCondition(
|
||||
}
|
||||
|
||||
function createProviderProperty(
|
||||
propName: string, provider: ProviderAst, providerValueExpressions: o.Expression[],
|
||||
isMulti: boolean, isEager: boolean, compileElement: CompileElement): o.Expression {
|
||||
propName: string, providerValueExpressions: o.Expression[], isMulti: boolean, isEager: boolean,
|
||||
compileElement: CompileElement): o.Expression {
|
||||
const view = compileElement.view;
|
||||
let resolvedProviderValueExpr: o.Expression;
|
||||
let type: o.Type;
|
||||
|
@ -6,7 +6,6 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {isPresent} from '../facade/lang';
|
||||
import * as o from '../output/output_ast';
|
||||
import {TemplateAst} from '../template_parser/template_ast';
|
||||
|
||||
@ -34,7 +33,7 @@ export class CompileMethod {
|
||||
if (this._newState.nodeIndex !== this._currState.nodeIndex ||
|
||||
this._newState.sourceAst !== this._currState.sourceAst) {
|
||||
const expr = this._updateDebugContext(this._newState);
|
||||
if (isPresent(expr)) {
|
||||
if (expr) {
|
||||
this._bodyStatements.push(expr.toStmt());
|
||||
}
|
||||
}
|
||||
@ -43,13 +42,12 @@ export class CompileMethod {
|
||||
private _updateDebugContext(newState: _DebugState): o.Expression {
|
||||
this._currState = this._newState = newState;
|
||||
if (this._debugEnabled) {
|
||||
const sourceLocation =
|
||||
isPresent(newState.sourceAst) ? newState.sourceAst.sourceSpan.start : null;
|
||||
const sourceLocation = newState.sourceAst ? newState.sourceAst.sourceSpan.start : null;
|
||||
|
||||
return o.THIS_EXPR.callMethod('debug', [
|
||||
o.literal(newState.nodeIndex),
|
||||
isPresent(sourceLocation) ? o.literal(sourceLocation.line) : o.NULL_EXPR,
|
||||
isPresent(sourceLocation) ? o.literal(sourceLocation.col) : o.NULL_EXPR
|
||||
sourceLocation ? o.literal(sourceLocation.line) : o.NULL_EXPR,
|
||||
sourceLocation ? o.literal(sourceLocation.col) : o.NULL_EXPR
|
||||
]);
|
||||
} else {
|
||||
return null;
|
||||
|
@ -8,7 +8,6 @@
|
||||
|
||||
import {CompileQueryMetadata, tokenReference} from '../compile_metadata';
|
||||
import {ListWrapper} from '../facade/collection';
|
||||
import {isPresent} from '../facade/lang';
|
||||
import {Identifiers, createIdentifier} from '../identifiers';
|
||||
import * as o from '../output/output_ast';
|
||||
|
||||
@ -33,7 +32,7 @@ export class CompileQuery {
|
||||
addValue(value: o.Expression, view: CompileView) {
|
||||
let currentView = view;
|
||||
const elPath: CompileElement[] = [];
|
||||
while (isPresent(currentView) && currentView !== this.view) {
|
||||
while (currentView && currentView !== this.view) {
|
||||
const parentEl = currentView.declarationElement;
|
||||
elPath.unshift(parentEl);
|
||||
currentView = parentEl.view;
|
||||
@ -67,7 +66,7 @@ export class CompileQuery {
|
||||
generateStatements(targetStaticMethod: CompileMethod, targetDynamicMethod: CompileMethod) {
|
||||
const values = createQueryValues(this._values);
|
||||
const updateStmts = [this.queryList.callMethod('reset', [o.literalArr(values)]).toStmt()];
|
||||
if (isPresent(this.ownerDirectiveExpression)) {
|
||||
if (this.ownerDirectiveExpression) {
|
||||
const valueExpr = this.meta.first ? this.queryList.prop('first') : this.queryList;
|
||||
updateStmts.push(
|
||||
this.ownerDirectiveExpression.prop(this.meta.propertyName).set(valueExpr).toStmt());
|
||||
@ -110,9 +109,7 @@ function mapNestedViews(
|
||||
]);
|
||||
}
|
||||
|
||||
export function createQueryList(
|
||||
query: CompileQueryMetadata, directiveInstance: o.Expression, propertyName: string,
|
||||
compileView: CompileView): o.Expression {
|
||||
export function createQueryList(propertyName: string, compileView: CompileView): o.Expression {
|
||||
compileView.fields.push(new o.ClassField(
|
||||
propertyName, o.importType(createIdentifier(Identifiers.QueryList), [o.DYNAMIC_TYPE])));
|
||||
const expr = o.THIS_EXPR.prop(propertyName);
|
||||
|
@ -12,7 +12,6 @@ import {EventHandlerVars, NameResolver} from '../compiler_util/expression_conver
|
||||
import {createPureProxy} from '../compiler_util/identifier_util';
|
||||
import {CompilerConfig} from '../config';
|
||||
import {isPresent} from '../facade/lang';
|
||||
import {Identifiers, createIdentifier} from '../identifiers';
|
||||
import * as o from '../output/output_ast';
|
||||
import {ViewType} from '../private_import_core';
|
||||
|
||||
@ -119,7 +118,7 @@ export class CompileView implements NameResolver {
|
||||
const directiveInstance = o.THIS_EXPR.prop('context');
|
||||
this.component.viewQueries.forEach((queryMeta, queryIndex) => {
|
||||
const propName = `_viewQuery_${tokenName(queryMeta.selectors[0])}_${queryIndex}`;
|
||||
const queryList = createQueryList(queryMeta, directiveInstance, propName, this);
|
||||
const queryList = createQueryList(propName, this);
|
||||
const query = new CompileQuery(queryMeta, queryList, directiveInstance, this);
|
||||
addQueryToTokenMap(viewQueries, query);
|
||||
});
|
||||
|
@ -11,7 +11,7 @@ import {ChangeDetectionStrategy, ViewEncapsulation} from '@angular/core';
|
||||
import {createEnumExpression} from '../compiler_util/identifier_util';
|
||||
import {Identifiers} from '../identifiers';
|
||||
import * as o from '../output/output_ast';
|
||||
import {ChangeDetectorStatus, ViewType} from '../private_import_core';
|
||||
import {ViewType} from '../private_import_core';
|
||||
|
||||
export class ViewTypeEnum {
|
||||
static fromValue(value: ViewType): o.Expression {
|
||||
@ -25,12 +25,6 @@ export class ViewEncapsulationEnum {
|
||||
}
|
||||
}
|
||||
|
||||
export class ChangeDetectionStrategyEnum {
|
||||
static fromValue(value: ChangeDetectionStrategy): o.Expression {
|
||||
return createEnumExpression(Identifiers.ChangeDetectionStrategy, value);
|
||||
}
|
||||
}
|
||||
|
||||
export class ChangeDetectorStatusEnum {
|
||||
static fromValue(value: ChangeDetectorStatusEnum): o.Expression {
|
||||
return createEnumExpression(Identifiers.ChangeDetectorStatus, value);
|
||||
|
@ -15,7 +15,6 @@ import {BoundEventAst, DirectiveAst} from '../template_parser/template_ast';
|
||||
|
||||
import {CompileElement} from './compile_element';
|
||||
import {CompileMethod} from './compile_method';
|
||||
import {ViewProperties} from './constants';
|
||||
import {getHandleEventMethodName} from './util';
|
||||
|
||||
export function bindOutputs(
|
||||
|
@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {CompileQueryMetadata, CompileTokenMetadata, tokenReference} from '../compile_metadata';
|
||||
import {CompileTokenMetadata, tokenReference} from '../compile_metadata';
|
||||
import * as o from '../output/output_ast';
|
||||
|
||||
import {CompileElement} from './compile_element';
|
||||
@ -17,16 +17,18 @@ import {CompileQuery} from './compile_query';
|
||||
// as we create embedded views before the <template> elements themselves.
|
||||
export function bindQueryValues(ce: CompileElement) {
|
||||
const queriesWithReads: _QueryWithRead[] = [];
|
||||
|
||||
ce.getProviderTokens().forEach((token) => {
|
||||
const queriesForProvider = ce.getQueriesFor(token);
|
||||
queriesWithReads.push(...queriesForProvider.map(query => new _QueryWithRead(query, token)));
|
||||
});
|
||||
|
||||
Object.keys(ce.referenceTokens).forEach(varName => {
|
||||
const token = ce.referenceTokens[varName];
|
||||
const varToken = {value: varName};
|
||||
queriesWithReads.push(
|
||||
...ce.getQueriesFor(varToken).map(query => new _QueryWithRead(query, varToken)));
|
||||
});
|
||||
|
||||
queriesWithReads.forEach((queryWithRead) => {
|
||||
let value: o.Expression;
|
||||
if (queryWithRead.read.identifier) {
|
||||
|
@ -9,8 +9,6 @@
|
||||
|
||||
import {CompileDirectiveMetadata, CompileDirectiveSummary, CompileIdentifierMetadata, CompileTokenMetadata, identifierName} from '../compile_metadata';
|
||||
import {createDiTokenExpression} from '../compiler_util/identifier_util';
|
||||
import {isPresent} from '../facade/lang';
|
||||
import {Identifiers, createIdentifier} from '../identifiers';
|
||||
import * as o from '../output/output_ast';
|
||||
import {ViewType} from '../private_import_core';
|
||||
|
||||
@ -23,7 +21,7 @@ export function getPropertyInView(
|
||||
} else {
|
||||
let viewProp: o.Expression = o.THIS_EXPR;
|
||||
let currView: CompileView = callingView;
|
||||
while (currView !== definedView && isPresent(currView.declarationElement.view)) {
|
||||
while (currView !== definedView && currView.declarationElement.view) {
|
||||
currView = currView.declarationElement.view;
|
||||
viewProp = viewProp.prop('parentView');
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ import {isPresent} from '../facade/lang';
|
||||
import {Identifiers, createIdentifier, identifierToken} from '../identifiers';
|
||||
import {createClassStmt} from '../output/class_builder';
|
||||
import * as o from '../output/output_ast';
|
||||
import {ParseSourceSpan} from '../parse_util';
|
||||
import {ChangeDetectorStatus, ViewType, isDefaultChangeDetectionStrategy} from '../private_import_core';
|
||||
import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, ElementAst, EmbeddedTemplateAst, NgContentAst, ReferenceAst, TemplateAst, TemplateAstVisitor, TextAst, VariableAst, templateVisitAll} from '../template_parser/template_ast';
|
||||
|
||||
@ -695,7 +694,6 @@ function generateCreateEmbeddedViewsMethod(view: CompileView): o.ClassMethod {
|
||||
view.nodes.forEach((node) => {
|
||||
if (node instanceof CompileElement) {
|
||||
if (node.embeddedView) {
|
||||
const parentNodeIndex = node.isRootElement() ? null : node.parent.nodeIndex;
|
||||
stmts.push(new o.IfStmt(
|
||||
nodeIndexVar.equals(o.literal(node.nodeIndex)),
|
||||
[new o.ReturnStatement(node.embeddedView.classExpr.instantiate([
|
||||
|
@ -449,6 +449,40 @@ describe('StaticReflector', () => {
|
||||
expect(annotations[0].providers[0].useValue.members[0]).toEqual('staticMethod');
|
||||
});
|
||||
|
||||
// #13605
|
||||
it('should not throw on unknown decorators', () => {
|
||||
const data = Object.create(DEFAULT_TEST_DATA);
|
||||
const file = '/tmp/src/app.component.ts';
|
||||
data[file] = `
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
export const enum TypeEnum {
|
||||
type
|
||||
}
|
||||
|
||||
export function MyValidationDecorator(p1: any, p2: any): any {
|
||||
return null;
|
||||
}
|
||||
|
||||
export function ValidationFunction(a1: any): any {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'my-app',
|
||||
template: "<h1>Hello {{name}}</h1>",
|
||||
})
|
||||
export class AppComponent {
|
||||
name = 'Angular';
|
||||
|
||||
@MyValidationDecorator( TypeEnum.type, ValidationFunction({option: 'value'}))
|
||||
myClassProp: number;
|
||||
}`;
|
||||
init(data);
|
||||
const appComponent = reflector.getStaticSymbol(file, 'AppComponent');
|
||||
expect(() => reflector.propMetadata(appComponent)).not.toThrow();
|
||||
});
|
||||
|
||||
describe('inheritance', () => {
|
||||
class ClassDecorator {
|
||||
constructor(public value: any) {}
|
||||
|
@ -210,5 +210,56 @@ const XMB = `
|
||||
<ph name="START_TAG_DIV_1"><ex><div></ex></ph><ph name="ICU"/><ph name="CLOSE_TAG_DIV"><ex></div></ex></ph>
|
||||
</msg>
|
||||
<msg id="1491627405349178954">it <ph name="START_BOLD_TEXT"><ex><b></ex></ph>should<ph name="CLOSE_BOLD_TEXT"><ex></b></ex></ph> work</msg>
|
||||
</messagebundle>
|
||||
</messagebundle>`;
|
||||
|
||||
const HTML = `
|
||||
<div>
|
||||
<h1 i18n>i18n attribute on tags</h1>
|
||||
|
||||
<div id="i18n-1"><p i18n>nested</p></div>
|
||||
|
||||
<div id="i18n-2"><p i18n="different meaning|">nested</p></div>
|
||||
|
||||
<div id="i18n-3"><p i18n><i>with placeholders</i></p></div>
|
||||
<div id="i18n-3b"><p i18n><i class="preserved-on-placeholders">with placeholders</i></p></div>
|
||||
|
||||
<div>
|
||||
<p id="i18n-4" i18n-title title="on not translatable node"></p>
|
||||
<p id="i18n-5" i18n i18n-title title="on translatable node"></p>
|
||||
<p id="i18n-6" i18n-title title></p>
|
||||
</div>
|
||||
|
||||
<!-- no ph below because the ICU node is the only child of the div, i.e. no text nodes -->
|
||||
<div i18n id="i18n-7">{count, plural, =0 {zero} =1 {one} =2 {two} other {<b>many</b>}}</div>
|
||||
|
||||
<div i18n id="i18n-8">
|
||||
{sex, select, m {male} f {female}}
|
||||
</div>
|
||||
<div i18n id="i18n-8b">
|
||||
{sexB, select, m {male} f {female}}
|
||||
</div>
|
||||
|
||||
<div i18n id="i18n-9">{{ "count = " + count }}</div>
|
||||
<div i18n id="i18n-10">sex = {{ sex }}</div>
|
||||
<div i18n id="i18n-11">{{ "custom name" //i18n(ph="CUSTOM_NAME") }}</div>
|
||||
</div>
|
||||
|
||||
<!-- i18n -->
|
||||
<h1 id="i18n-12" >Markers in html comments</h1>
|
||||
<div id="i18n-13" i18n-title title="in a translatable section"></div>
|
||||
<div id="i18n-14">{count, plural, =0 {zero} =1 {one} =2 {two} other {<b>many</b>}}</div>
|
||||
<!-- /i18n -->
|
||||
|
||||
<div id="i18n-15"><ng-container i18n>it <b>should</b> work</ng-container></div>
|
||||
|
||||
<!-- make sure that ICU messages are not treated as text nodes -->
|
||||
<div i18n="desc">{
|
||||
response.getItemsList().length,
|
||||
plural,
|
||||
=0 {Found no results}
|
||||
=1 {Found one result}
|
||||
other {Found {{response.getItemsList().length}} results}
|
||||
}</div>
|
||||
|
||||
<div i18n id="i18n-18">foo<a i18n-title title="in a translatable section">bar</a></div>
|
||||
`;
|
||||
|
@ -1323,17 +1323,30 @@ Reference "#a" is defined several times ("<div #a></div><div [ERROR ->]#a></div>
|
||||
|
||||
});
|
||||
|
||||
|
||||
it('should work with *... and use the attribute name as property binding name', () => {
|
||||
expect(humanizeTplAst(parse('<div *ngIf="test">', [ngIf]))).toEqual([
|
||||
[EmbeddedTemplateAst], [DirectiveAst, ngIf],
|
||||
[BoundDirectivePropertyAst, 'ngIf', 'test'], [ElementAst, 'div']
|
||||
[EmbeddedTemplateAst],
|
||||
[DirectiveAst, ngIf],
|
||||
[BoundDirectivePropertyAst, 'ngIf', 'test'],
|
||||
[ElementAst, 'div'],
|
||||
]);
|
||||
|
||||
// https://github.com/angular/angular/issues/13800
|
||||
expect(humanizeTplAst(parse('<div *ngIf="-1">', [ngIf]))).toEqual([
|
||||
[EmbeddedTemplateAst],
|
||||
[DirectiveAst, ngIf],
|
||||
[BoundDirectivePropertyAst, 'ngIf', '0 - 1'],
|
||||
[ElementAst, 'div'],
|
||||
]);
|
||||
});
|
||||
|
||||
it('should work with *... and empty value', () => {
|
||||
expect(humanizeTplAst(parse('<div *ngIf>', [ngIf]))).toEqual([
|
||||
[EmbeddedTemplateAst], [DirectiveAst, ngIf],
|
||||
[BoundDirectivePropertyAst, 'ngIf', 'null'], [ElementAst, 'div']
|
||||
[EmbeddedTemplateAst],
|
||||
[DirectiveAst, ngIf],
|
||||
[BoundDirectivePropertyAst, 'ngIf', 'null'],
|
||||
[ElementAst, 'div'],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
@ -13,7 +13,6 @@ import {Type} from '../type';
|
||||
|
||||
import {ElementRef} from './element_ref';
|
||||
import {AppView} from './view';
|
||||
import {ViewContainer} from './view_container';
|
||||
import {ViewRef} from './view_ref';
|
||||
import {ViewUtils} from './view_utils';
|
||||
|
||||
@ -86,11 +85,6 @@ export class ComponentRef_<C> extends ComponentRef<C> {
|
||||
onDestroy(callback: Function): void { this.hostView.onDestroy(callback); }
|
||||
}
|
||||
|
||||
/**
|
||||
* @experimental
|
||||
*/
|
||||
const EMPTY_CONTEXT = new Object();
|
||||
|
||||
/**
|
||||
* @stable
|
||||
*/
|
||||
|
@ -8,7 +8,6 @@
|
||||
|
||||
import {ElementRef} from './element_ref';
|
||||
import {AppView} from './view';
|
||||
import {ViewContainer} from './view_container';
|
||||
import {EmbeddedViewRef} from './view_ref';
|
||||
|
||||
|
||||
|
@ -11,7 +11,7 @@ import {ChangeDetectorRef, ChangeDetectorStatus} from '../change_detection/chang
|
||||
import {Injector, THROW_IF_NOT_FOUND} from '../di/injector';
|
||||
import {isPresent} from '../facade/lang';
|
||||
import {WtfScopeFn, wtfCreateScope, wtfLeave} from '../profile/profile';
|
||||
import {DirectRenderer, RenderComponentType, RenderDebugInfo, Renderer} from '../render/api';
|
||||
import {DirectRenderer, RenderComponentType, Renderer} from '../render/api';
|
||||
|
||||
import {AnimationViewContext} from './animation_view_context';
|
||||
import {ComponentRef} from './component_factory';
|
||||
|
@ -7,10 +7,8 @@
|
||||
*/
|
||||
|
||||
import {Injector} from '../di/injector';
|
||||
import {isPresent} from '../facade/lang';
|
||||
|
||||
import {ElementRef} from './element_ref';
|
||||
import {QueryList} from './query_list';
|
||||
import {AppView} from './view';
|
||||
import {ViewContainerRef_} from './view_container_ref';
|
||||
import {ViewType} from './view_type';
|
||||
|
@ -15,7 +15,6 @@ import {ViewEncapsulation} from '../metadata/view';
|
||||
import {RenderComponentType, RenderDebugInfo, Renderer, RootRenderer} from '../render/api';
|
||||
import {Sanitizer} from '../security';
|
||||
import {VERSION} from '../version';
|
||||
import {NgZone} from '../zone/ng_zone';
|
||||
|
||||
import {ExpressionChangedAfterItHasBeenCheckedError} from './errors';
|
||||
import {AppView} from './view';
|
||||
@ -23,7 +22,6 @@ import {AppView} from './view';
|
||||
@Injectable()
|
||||
export class ViewUtils {
|
||||
sanitizer: Sanitizer;
|
||||
private _nextCompTypeId: number = 0;
|
||||
|
||||
constructor(
|
||||
private _renderer: RootRenderer, sanitizer: Sanitizer,
|
||||
|
@ -138,7 +138,7 @@ export function main() {
|
||||
@Component({
|
||||
selector: 'child',
|
||||
template:
|
||||
'(<template [ngTemplateOutlet]="templateRef" [ngOutletContext]="templateCtx"></template>)'
|
||||
'(<ng-container [ngTemplateOutlet]="templateRef" [ngOutletContext]="templateCtx"></ng-container>)'
|
||||
})
|
||||
class Child {
|
||||
@Input()
|
||||
|
@ -23,8 +23,15 @@ function declareTests({useJit}: {useJit: boolean}) {
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureCompiler({useJit: useJit});
|
||||
TestBed.configureTestingModule(
|
||||
{declarations: [MyComp, NeedsContentChildren, NeedsViewChildren, TextDirective, Simple]});
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
MyComp,
|
||||
NeedsContentChildren,
|
||||
NeedsViewChildren,
|
||||
TextDirective,
|
||||
Simple,
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('should support the "i18n" attribute', () => {
|
||||
|
@ -421,7 +421,7 @@ export function main() {
|
||||
TestBed.overrideDirective(
|
||||
SimpleDirective, {set: {providers: [{provide: 'service', useValue: 'parentService'}]}});
|
||||
const el = createComponent(
|
||||
'<div simpleDirective><template [ngIf]="true"><div *ngIf="true" needsService></div></template></div>');
|
||||
'<div simpleDirective><ng-container *ngIf="true"><div *ngIf="true" needsService></div></ng-container></div>');
|
||||
expect(el.children[0].children[0].injector.get(NeedsService).service)
|
||||
.toEqual('parentService');
|
||||
});
|
||||
|
@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Component, ComponentRef, Injectable, Injector} from '@angular/core';
|
||||
import {Component, ComponentRef, Injectable} from '@angular/core';
|
||||
import {DebugDomRootRenderer} from '@angular/core/src/debug/debug_renderer';
|
||||
import {RootRenderer} from '@angular/core/src/render/api';
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
@ -152,7 +152,7 @@ export function main() {
|
||||
it('should update any template comment property/attributes', () => {
|
||||
|
||||
TestBed.overrideComponent(
|
||||
MyComp2, {set: {template: '<template [ngIf]="ctxBoolProp"></template>'}});
|
||||
MyComp2, {set: {template: '<ng-container *ngIf="ctxBoolProp"></ng-container>'}});
|
||||
const fixture = TestBed.createComponent(MyComp2);
|
||||
|
||||
(<MyComp2>fixture.componentInstance).ctxBoolProp = true;
|
||||
@ -163,7 +163,7 @@ export function main() {
|
||||
|
||||
it('should add and remove fragments', () => {
|
||||
TestBed.overrideComponent(
|
||||
MyComp2, {set: {template: '<template [ngIf]="ctxBoolProp">hello</template>'}});
|
||||
MyComp2, {set: {template: '<ng-container *ngIf="ctxBoolProp">hello</ng-container>'}});
|
||||
const fixture = TestBed.createComponent(MyComp2);
|
||||
|
||||
const rootEl = getRenderElement(fixture.nativeElement);
|
||||
|
@ -71,4 +71,4 @@ Promise
|
||||
return Promise.all(
|
||||
allSpecFiles.map(function(moduleName) { return System.import(moduleName); }));
|
||||
})
|
||||
.then(__karma__.start, __karma__.error);
|
||||
.then(__karma__.start, (v) => console.error(v));
|
||||
|
@ -133,7 +133,7 @@ export class RouterLink {
|
||||
*/
|
||||
@Directive({selector: 'a[routerLink]'})
|
||||
export class RouterLinkWithHref implements OnChanges, OnDestroy {
|
||||
@Input() target: string;
|
||||
@HostBinding('attr.target') @Input() target: string;
|
||||
@Input() queryParams: {[k: string]: any};
|
||||
@Input() fragment: string;
|
||||
@Input() preserveQueryParams: boolean;
|
||||
|
@ -526,6 +526,7 @@ export class Router {
|
||||
*/
|
||||
navigate(commands: any[], extras: NavigationExtras = {skipLocationChange: false}):
|
||||
Promise<boolean> {
|
||||
validateCommands(commands);
|
||||
if (typeof extras.queryParams === 'object' && extras.queryParams !== null) {
|
||||
extras.queryParams = this.removeEmptyProps(extras.queryParams);
|
||||
}
|
||||
@ -1237,3 +1238,12 @@ function getOutlet(outletMap: RouterOutletMap, route: ActivatedRoute): RouterOut
|
||||
}
|
||||
return outlet;
|
||||
}
|
||||
|
||||
function validateCommands(commands: string[]): void {
|
||||
for (let i = 0; i < commands.length; i++) {
|
||||
const cmd = commands[i];
|
||||
if (cmd == null) {
|
||||
throw new Error(`The requested path contains ${cmd} segment at index ${i}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ function equalSegmentGroups(container: UrlSegmentGroup, containee: UrlSegmentGro
|
||||
|
||||
function containsQueryParams(
|
||||
container: {[k: string]: string}, containee: {[k: string]: string}): boolean {
|
||||
return Object.keys(containee) <= Object.keys(container) &&
|
||||
return Object.keys(containee).length <= Object.keys(container).length &&
|
||||
Object.keys(containee).every(key => containee[key] === container[key]);
|
||||
}
|
||||
|
||||
|
@ -536,6 +536,17 @@ describe('Integration', () => {
|
||||
expect(cmp.recordedParams).toEqual([{name: '1'}]);
|
||||
})));
|
||||
|
||||
it('should throw an error when one of the commands is null/undefined',
|
||||
fakeAsync(inject([Router], (router: Router) => {
|
||||
createRoot(router, RootCmp);
|
||||
|
||||
router.resetConfig([{path: 'query', component: EmptyQueryParamsCmp}]);
|
||||
|
||||
expect(() => router.navigate([
|
||||
undefined, 'query'
|
||||
])).toThrowError(`The requested path contains undefined segment at index 0`);
|
||||
})));
|
||||
|
||||
it('should push params only when they change', fakeAsync(inject([Router], (router: Router) => {
|
||||
const fixture = createRoot(router, RootCmp);
|
||||
|
||||
@ -998,6 +1009,7 @@ describe('Integration', () => {
|
||||
|
||||
const native = fixture.nativeElement.querySelector('a');
|
||||
expect(native.getAttribute('href')).toEqual('/team/33/simple');
|
||||
expect(native.getAttribute('target')).toEqual('_self');
|
||||
native.click();
|
||||
advance(fixture);
|
||||
|
||||
@ -2646,7 +2658,8 @@ function expectEvents(events: Event[], pairs: any[]) {
|
||||
}
|
||||
}
|
||||
|
||||
@Component({selector: 'link-cmp', template: `<a routerLink="/team/33/simple">link</a>`})
|
||||
@Component(
|
||||
{selector: 'link-cmp', template: `<a routerLink="/team/33/simple" [target]="'_self'">link</a>`})
|
||||
class StringLinkCmp {
|
||||
}
|
||||
|
||||
|
@ -102,8 +102,8 @@ describe('UrlTree', () => {
|
||||
});
|
||||
|
||||
it('should return true when container contains containees queryParams', () => {
|
||||
const t1 = serializer.parse('/one/two?test=1&page=5');
|
||||
const t2 = serializer.parse('/one/two?test=1');
|
||||
const t1 = serializer.parse('/one/two?test=1&u=5');
|
||||
const t2 = serializer.parse('/one/two?u=5');
|
||||
expect(containsTree(t1, t2, false)).toBe(true);
|
||||
});
|
||||
|
||||
|
@ -29,7 +29,7 @@ export function init(moduleRef: NgModuleRef<AppModule>) {
|
||||
}
|
||||
|
||||
function detectChanges() {
|
||||
for (var i = 0; i < 10; i++) {
|
||||
for (let i = 0; i < 10; i++) {
|
||||
appRef.tick();
|
||||
}
|
||||
detectChangesRuns += 10;
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "angular-srcs",
|
||||
"version": "2.4.2",
|
||||
"version": "2.4.3",
|
||||
"private": true,
|
||||
"branchPattern": "2.0.*",
|
||||
"description": "Angular 2 - a web framework for modern web apps",
|
||||
|
@ -82,9 +82,7 @@ System.import('@angular/core/testing')
|
||||
});
|
||||
}));
|
||||
})
|
||||
.then(
|
||||
function() { __karma__.start(); },
|
||||
function(error) { __karma__.error(error.stack || error); });
|
||||
.then(function() { __karma__.start(); }, function(error) { console.error(error); });
|
||||
|
||||
|
||||
function onlySpecFiles(path) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@angular/tsc-wrapped",
|
||||
"version": "0.5.0",
|
||||
"version": "0.5.1",
|
||||
"description": "Wraps the tsc CLI, allowing extensions.",
|
||||
"homepage": "https://github.com/angular/angular/tree/master/tools/tsc-wrapped",
|
||||
"bugs": "https://github.com/angular/angular/issues",
|
||||
|
Reference in New Issue
Block a user