110 lines
3.3 KiB
TypeScript
Raw Normal View History

/**
* @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
*/
2016-09-08 19:25:25 -07:00
import {Attribute, Directive, Host, Input, TemplateRef, ViewContainerRef} from '@angular/core';
import {NgLocalization, getPluralCategory} from '../localization';
2016-03-04 16:32:22 -08:00
import {SwitchView} from './ng_switch';
2016-03-04 16:32:22 -08:00
/**
* @ngModule CommonModule
2016-03-04 16:32:22 -08:00
*
* @whatItDoes Adds / removes DOM sub-trees based on a numeric value. Tailored for pluralization.
*
* @howToUse
* ```
* <some-element [ngPlural]="value">
* <template ngPluralCase="=0">there is nothing</template>
* <template ngPluralCase="=1">there is one</template>
* <template ngPluralCase="few">there are a few</template>
* </some-element>
* ```
2016-03-04 16:32:22 -08:00
*
* @description
2016-03-04 16:32:22 -08:00
*
* Displays DOM sub-trees that match the switch expression value, or failing that, DOM sub-trees
* that match the switch expression's pluralization category.
2016-03-04 16:32:22 -08:00
*
* To use this directive you must provide a container element that sets the `[ngPlural]` attribute
* to a switch expression. Inner elements with a `[ngPluralCase]` will display based on their
* expression:
* - if `[ngPluralCase]` is set to a value starting with `=`, it will only display if the value
* matches the switch expression exactly,
* - otherwise, the view will be treated as a "category match", and will only display if exact
* value matches aren't found and the value maps to its category for the defined locale.
*
* See http://cldr.unicode.org/index/cldr-spec/plural-rules
2016-03-04 16:32:22 -08:00
*
* @experimental
2016-03-04 16:32:22 -08:00
*/
@Directive({selector: '[ngPlural]'})
export class NgPlural {
2016-03-04 16:32:22 -08:00
private _switchValue: number;
private _activeView: SwitchView;
private _caseViews: {[k: string]: SwitchView} = {};
2016-03-04 16:32:22 -08:00
constructor(private _localization: NgLocalization) {}
@Input()
set ngPlural(value: number) {
this._switchValue = value;
this._updateView();
}
addCase(value: string, switchView: SwitchView): void { this._caseViews[value] = switchView; }
2016-03-04 16:32:22 -08:00
2016-09-22 10:34:00 -07:00
private _updateView(): void {
2016-03-04 16:32:22 -08:00
this._clearViews();
2016-09-08 19:25:25 -07:00
const cases = Object.keys(this._caseViews);
const key = getPluralCategory(this._switchValue, cases, this._localization);
this._activateView(this._caseViews[key]);
2016-03-04 16:32:22 -08:00
}
2016-09-22 10:34:00 -07:00
private _clearViews() {
2016-09-08 19:25:25 -07:00
if (this._activeView) this._activeView.destroy();
2016-03-04 16:32:22 -08:00
}
2016-09-22 10:34:00 -07:00
private _activateView(view: SwitchView) {
2016-09-08 19:25:25 -07:00
if (view) {
this._activeView = view;
this._activeView.create();
}
2016-03-04 16:32:22 -08:00
}
}
/**
* @ngModule CommonModule
*
* @whatItDoes Creates a view that will be added/removed from the parent {@link NgPlural} when the
* given expression matches the plural expression according to CLDR rules.
*
* @howToUse
* ```
* <some-element [ngPlural]="value">
* <template ngPluralCase="=0">...</template>
* <template ngPluralCase="other">...</template>
* </some-element>
*```
*
* See {@link NgPlural} for more details and example.
*
* @experimental
*/
@Directive({selector: '[ngPluralCase]'})
export class NgPluralCase {
constructor(
@Attribute('ngPluralCase') public value: string, template: TemplateRef<Object>,
viewContainer: ViewContainerRef, @Host() ngPlural: NgPlural) {
const isANumber: boolean = !isNaN(Number(value));
ngPlural.addCase(isANumber ? `=${value}` : value, new SwitchView(viewContainer, template));
}
}