diff --git a/modules/@angular/common/src/directives/ng_plural.ts b/modules/@angular/common/src/directives/ng_plural.ts index 3577e64b3e..a75590a2e1 100644 --- a/modules/@angular/common/src/directives/ng_plural.ts +++ b/modules/@angular/common/src/directives/ng_plural.ts @@ -6,11 +6,14 @@ * found in the LICENSE file at https://angular.io/license */ -import {AfterContentInit, Attribute, ContentChildren, Directive, Input, QueryList, TemplateRef, ViewContainerRef} from '@angular/core'; +import {Attribute, Directive, Host, Input, OnInit, TemplateRef, ViewContainerRef} from '@angular/core'; + import {isPresent} from '../facade/lang'; import {NgLocalization, getPluralCategory} from '../localization'; + import {SwitchView} from './ng_switch'; + /** * `ngPlural` is an i18n directive that displays DOM sub-trees that match the switch expression * value, or failing that, DOM sub-trees that match the switch expression's pluralization category. @@ -64,27 +67,11 @@ import {SwitchView} from './ng_switch'; * ``` * @experimental */ - -@Directive({selector: '[ngPluralCase]'}) -export class NgPluralCase { - /** @internal */ - _view: SwitchView; - constructor( - @Attribute('ngPluralCase') public value: string, template: TemplateRef, - viewContainer: ViewContainerRef) { - this._view = new SwitchView(viewContainer, template); - } -} - -/** - * @experimental - */ @Directive({selector: '[ngPlural]'}) -export class NgPlural implements AfterContentInit { +export class NgPlural { private _switchValue: number; private _activeView: SwitchView; private _caseViews: {[k: string]: SwitchView} = {}; - @ContentChildren(NgPluralCase) cases: QueryList = null; constructor(private _localization: NgLocalization) {} @@ -94,12 +81,7 @@ export class NgPlural implements AfterContentInit { this._updateView(); } - ngAfterContentInit() { - this.cases.forEach((pluralCase: NgPluralCase): void => { - this._caseViews[pluralCase.value] = pluralCase._view; - }); - this._updateView(); - } + addCase(value: string, switchView: SwitchView): void { this._caseViews[value] = switchView; } /** @internal */ _updateView(): void { @@ -122,3 +104,15 @@ export class NgPlural implements AfterContentInit { this._activeView.create(); } } + +/** + * @experimental + */ +@Directive({selector: '[ngPluralCase]'}) +export class NgPluralCase { + constructor( + @Attribute('ngPluralCase') public value: string, template: TemplateRef, + viewContainer: ViewContainerRef, @Host() ngPlural: NgPlural) { + ngPlural.addCase(value, new SwitchView(viewContainer, template)); + } +} diff --git a/modules/@angular/common/test/directives/ng_plural_spec.ts b/modules/@angular/common/test/directives/ng_plural_spec.ts index 179400e6b0..1106d5b5e6 100644 --- a/modules/@angular/common/test/directives/ng_plural_spec.ts +++ b/modules/@angular/common/test/directives/ng_plural_spec.ts @@ -42,6 +42,27 @@ 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', + inject( + [TestComponentBuilder, AsyncTestCompleter], + (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { + var template = '
' + + '
    ' + + '' + + '
'; + + tcb.overrideTemplate(TestComponent, template) + .createAsync(TestComponent) + .then((fixture) => { + fixture.debugElement.componentInstance.switchValue = 0; + expect(() => fixture.detectChanges()).not.toThrow(); + async.done(); + }); + })); + + it('should be applicable to elements', inject( [TestComponentBuilder, AsyncTestCompleter], diff --git a/tools/public_api_guard/common/index.d.ts b/tools/public_api_guard/common/index.d.ts index ea7228ad2b..fbd6d10718 100644 --- a/tools/public_api_guard/common/index.d.ts +++ b/tools/public_api_guard/common/index.d.ts @@ -437,17 +437,16 @@ export declare class NgModel extends NgControl implements OnChanges { } /** @experimental */ -export declare class NgPlural implements AfterContentInit { - cases: QueryList; +export declare class NgPlural { ngPlural: number; constructor(_localization: NgLocalization); - ngAfterContentInit(): void; + addCase(value: string, switchView: SwitchView): void; } /** @experimental */ export declare class NgPluralCase { value: string; - constructor(value: string, template: TemplateRef, viewContainer: ViewContainerRef); + constructor(value: string, template: TemplateRef, viewContainer: ViewContainerRef, ngPlural: NgPlural); } /** @experimental */