fix(ngSwitch): use switchCase instead of switchWhen (#9076)

This commit is contained in:
Rob Wormald 2016-06-09 22:52:30 -07:00 committed by GitHub
parent f39c9c9e75
commit e1fcab777c
5 changed files with 88 additions and 45 deletions

View File

@ -9,5 +9,5 @@ export {NgFor} from './directives/ng_for';
export {NgIf} from './directives/ng_if'; export {NgIf} from './directives/ng_if';
export {NgLocalization, NgPlural, NgPluralCase} from './directives/ng_plural'; export {NgLocalization, NgPlural, NgPluralCase} from './directives/ng_plural';
export {NgStyle} from './directives/ng_style'; export {NgStyle} from './directives/ng_style';
export {NgSwitch, NgSwitchDefault, NgSwitchWhen} from './directives/ng_switch'; export {NgSwitch, NgSwitchCase, NgSwitchDefault} from './directives/ng_switch';
export {NgTemplateOutlet} from './directives/ng_template_outlet'; export {NgTemplateOutlet} from './directives/ng_template_outlet';

View File

@ -5,10 +5,11 @@ import {NgFor} from './ng_for';
import {NgIf} from './ng_if'; import {NgIf} from './ng_if';
import {NgPlural, NgPluralCase} from './ng_plural'; import {NgPlural, NgPluralCase} from './ng_plural';
import {NgStyle} from './ng_style'; import {NgStyle} from './ng_style';
import {NgSwitch, NgSwitchDefault, NgSwitchWhen} from './ng_switch'; import {NgSwitch, NgSwitchCase, NgSwitchDefault} from './ng_switch';
import {NgTemplateOutlet} from './ng_template_outlet'; import {NgTemplateOutlet} from './ng_template_outlet';
/** /**
* A collection of Angular core directives that are likely to be used in each and every Angular * A collection of Angular core directives that are likely to be used in each and every Angular
* application. * application.
@ -58,7 +59,7 @@ export const CORE_DIRECTIVES: Type[] = /*@ts2dart_const*/[
NgTemplateOutlet, NgTemplateOutlet,
NgStyle, NgStyle,
NgSwitch, NgSwitch,
NgSwitchWhen, NgSwitchCase,
NgSwitchDefault, NgSwitchDefault,
NgPlural, NgPlural,
NgPluralCase, NgPluralCase,

View File

@ -3,7 +3,7 @@ import {Directive, Host, TemplateRef, ViewContainerRef} from '@angular/core';
import {ListWrapper, Map} from '../facade/collection'; import {ListWrapper, Map} from '../facade/collection';
import {isBlank, isPresent, normalizeBlank} from '../facade/lang'; import {isBlank, isPresent, normalizeBlank} from '../facade/lang';
const _WHEN_DEFAULT = /*@ts2dart_const*/ new Object(); const _CASE_DEFAULT = /*@ts2dart_const*/ new Object();
export class SwitchView { export class SwitchView {
constructor( constructor(
@ -17,17 +17,17 @@ export class SwitchView {
/** /**
* Adds or removes DOM sub-trees when their match expressions match the switch expression. * Adds or removes DOM sub-trees when their match expressions match the switch expression.
* *
* Elements within `NgSwitch` but without `NgSwitchWhen` or `NgSwitchDefault` directives will be * Elements within `NgSwitch` but without `ngSwitchCase` or `NgSwitchDefault` directives will be
* preserved at the location as specified in the template. * preserved at the location as specified in the template.
* *
* `NgSwitch` simply inserts nested elements based on which match expression matches the value * `NgSwitch` simply inserts nested elements based on which match expression matches the value
* obtained from the evaluated switch expression. In other words, you define a container element * obtained from the evaluated switch expression. In other words, you define a container element
* (where you place the directive with a switch expression on the * (where you place the directive with a switch expression on the
* `[ngSwitch]="..."` attribute), define any inner elements inside of the directive and * `[ngSwitch]="..."` attribute), define any inner elements inside of the directive and
* place a `[ngSwitchWhen]` attribute per element. * place a `[ngSwitchCase]` attribute per element.
* *
* The `ngSwitchWhen` property is used to inform `NgSwitch` which element to display when the * The `ngSwitchCase` property is used to inform `NgSwitch` which element to display when the
* expression is evaluated. If a matching expression is not found via a `ngSwitchWhen` property * expression is evaluated. If a matching expression is not found via a `ngSwitchCase` property
* then an element with the `ngSwitchDefault` attribute is displayed. * then an element with the `ngSwitchDefault` attribute is displayed.
* *
* ### Example ([live demo](http://plnkr.co/edit/DQMTII95CbuqWrl3lYAs?p=preview)) * ### Example ([live demo](http://plnkr.co/edit/DQMTII95CbuqWrl3lYAs?p=preview))
@ -40,24 +40,24 @@ export class SwitchView {
* <button (click)="inc()">Increment</button> * <button (click)="inc()">Increment</button>
* *
* <div [ngSwitch]="value"> * <div [ngSwitch]="value">
* <p *ngSwitchWhen="'init'">increment to start</p> * <p *ngSwitchCase="'init'">increment to start</p>
* <p *ngSwitchWhen="0">0, increment again</p> * <p *ngSwitchCase="0">0, increment again</p>
* <p *ngSwitchWhen="1">1, increment again</p> * <p *ngSwitchCase="1">1, increment again</p>
* <p *ngSwitchWhen="2">2, stop incrementing</p> * <p *ngSwitchCase="2">2, stop incrementing</p>
* <p *ngSwitchDefault>&gt; 2, STOP!</p> * <p *ngSwitchDefault>&gt; 2, STOP!</p>
* </div> * </div>
* *
* <!-- alternate syntax --> * <!-- alternate syntax -->
* *
* <p [ngSwitch]="value"> * <p [ngSwitch]="value">
* <template ngSwitchWhen="init">increment to start</template> * <template ngSwitchCase="init">increment to start</template>
* <template [ngSwitchWhen]="0">0, increment again</template> * <template [ngSwitchCase]="0">0, increment again</template>
* <template [ngSwitchWhen]="1">1, increment again</template> * <template [ngSwitchCase]="1">1, increment again</template>
* <template [ngSwitchWhen]="2">2, stop incrementing</template> * <template [ngSwitchCase]="2">2, stop incrementing</template>
* <template ngSwitchDefault>&gt; 2, STOP!</template> * <template ngSwitchDefault>&gt; 2, STOP!</template>
* </p> * </p>
* `, * `,
* directives: [NgSwitch, NgSwitchWhen, NgSwitchDefault] * directives: [NgSwitch, ngSwitchCase, NgSwitchDefault]
* }) * })
* export class App { * export class App {
* value = 'init'; * value = 'init';
@ -88,7 +88,7 @@ export class NgSwitch {
var views = this._valueViews.get(value); var views = this._valueViews.get(value);
if (isBlank(views)) { if (isBlank(views)) {
this._useDefault = true; this._useDefault = true;
views = normalizeBlank(this._valueViews.get(_WHEN_DEFAULT)); views = normalizeBlank(this._valueViews.get(_CASE_DEFAULT));
} }
this._activateViews(views); this._activateViews(views);
@ -96,14 +96,14 @@ export class NgSwitch {
} }
/** @internal */ /** @internal */
_onWhenValueChanged(oldWhen: any, newWhen: any, view: SwitchView): void { _onCaseValueChanged(oldCase: any, newCase: any, view: SwitchView): void {
this._deregisterView(oldWhen, view); this._deregisterView(oldCase, view);
this._registerView(newWhen, view); this._registerView(newCase, view);
if (oldWhen === this._switchValue) { if (oldCase === this._switchValue) {
view.destroy(); view.destroy();
ListWrapper.remove(this._activeViews, view); ListWrapper.remove(this._activeViews, view);
} else if (newWhen === this._switchValue) { } else if (newCase === this._switchValue) {
if (this._useDefault) { if (this._useDefault) {
this._useDefault = false; this._useDefault = false;
this._emptyAllActiveViews(); this._emptyAllActiveViews();
@ -115,7 +115,7 @@ export class NgSwitch {
// Switch to default when there is no more active ViewContainers // Switch to default when there is no more active ViewContainers
if (this._activeViews.length === 0 && !this._useDefault) { if (this._activeViews.length === 0 && !this._useDefault) {
this._useDefault = true; this._useDefault = true;
this._activateViews(this._valueViews.get(_WHEN_DEFAULT)); this._activateViews(this._valueViews.get(_CASE_DEFAULT));
} }
} }
@ -151,8 +151,8 @@ export class NgSwitch {
/** @internal */ /** @internal */
_deregisterView(value: any, view: SwitchView): void { _deregisterView(value: any, view: SwitchView): void {
// `_WHEN_DEFAULT` is used a marker for non-registered whens // `_CASE_DEFAULT` is used a marker for non-registered cases
if (value === _WHEN_DEFAULT) return; if (value === _CASE_DEFAULT) return;
var views = this._valueViews.get(value); var views = this._valueViews.get(value);
if (views.length == 1) { if (views.length == 1) {
this._valueViews.delete(value); this._valueViews.delete(value);
@ -163,7 +163,7 @@ export class NgSwitch {
} }
/** /**
* Insert the sub-tree when the `ngSwitchWhen` expression evaluates to the same value as the * Insert the sub-tree when the `ngSwitchCase` expression evaluates to the same value as the
* enclosing switch expression. * enclosing switch expression.
* *
* If multiple match expression match the switch expression value, all of them are displayed. * If multiple match expression match the switch expression value, all of them are displayed.
@ -172,13 +172,16 @@ export class NgSwitch {
* *
* @experimental * @experimental
*/ */
@Directive({selector: '[ngSwitchWhen]', inputs: ['ngSwitchWhen']}) @Directive({selector: '[ngSwitchCase],[ngSwitchWhen]', inputs: ['ngSwitchCase', 'ngSwitchWhen']})
export class NgSwitchWhen { export class NgSwitchCase {
// `_WHEN_DEFAULT` is used as a marker for a not yet initialized value // `_CASE_DEFAULT` is used as a marker for a not yet initialized value
/** @internal */ /** @internal */
_value: any = _WHEN_DEFAULT; _value: any = _CASE_DEFAULT;
/** @internal */ /** @internal */
_view: SwitchView; _view: SwitchView;
// TODO: remove when fully deprecated
/** @internal */
_warned: boolean;
private _switch: NgSwitch; private _switch: NgSwitch;
constructor( constructor(
@ -188,8 +191,17 @@ export class NgSwitchWhen {
this._view = new SwitchView(viewContainer, templateRef); this._view = new SwitchView(viewContainer, templateRef);
} }
set ngSwitchCase(value: any) {
this._switch._onCaseValueChanged(this._value, value, this._view);
this._value = value;
}
set ngSwitchWhen(value: any) { set ngSwitchWhen(value: any) {
this._switch._onWhenValueChanged(this._value, value, this._view); if (!this._warned) {
this._warned = true;
console.warn('*ngSwitchWhen is deprecated and will be removed. Use *ngSwitchCase instead');
}
this._switch._onCaseValueChanged(this._value, value, this._view);
this._value = value; this._value = value;
} }
} }
@ -207,6 +219,6 @@ export class NgSwitchDefault {
constructor( constructor(
viewContainer: ViewContainerRef, templateRef: TemplateRef<Object>, viewContainer: ViewContainerRef, templateRef: TemplateRef<Object>,
@Host() sswitch: NgSwitch) { @Host() sswitch: NgSwitch) {
sswitch._registerView(_WHEN_DEFAULT, new SwitchView(viewContainer, templateRef)); sswitch._registerView(_CASE_DEFAULT, new SwitchView(viewContainer, templateRef));
} }
} }

View File

@ -3,12 +3,41 @@ import {AsyncTestCompleter} from '@angular/core/testing/testing_internal';
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {TestComponentBuilder, ComponentFixture} from '@angular/compiler/testing'; import {TestComponentBuilder, ComponentFixture} from '@angular/compiler/testing';
import {NgSwitch, NgSwitchWhen, NgSwitchDefault} from '@angular/common'; import {NgSwitch, NgSwitchCase, NgSwitchDefault} from '@angular/common';
export function main() { export function main() {
describe('switch', () => { describe('switch', () => {
describe('switch value changes', () => { describe('switch value changes', () => {
it('should switch amongst when values', it('should switch amongst when values',
inject(
[TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = '<div>' +
'<ul [ngSwitch]="switchValue">' +
'<template ngSwitchCase="a"><li>when a</li></template>' +
'<template ngSwitchCase="b"><li>when b</li></template>' +
'</ul></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('');
fixture.debugElement.componentInstance.switchValue = 'a';
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('when a');
fixture.debugElement.componentInstance.switchValue = 'b';
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('when b');
async.done();
});
}));
// TODO(robwormald): deprecate and remove
it('should switch amongst when values using switchWhen',
inject( inject(
[TestComponentBuilder, AsyncTestCompleter], [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
@ -42,7 +71,7 @@ export function main() {
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = '<div>' + var template = '<div>' +
'<ul [ngSwitch]="switchValue">' + '<ul [ngSwitch]="switchValue">' +
'<li template="ngSwitchWhen \'a\'">when a</li>' + '<li template="ngSwitchCase \'a\'">when a</li>' +
'<li template="ngSwitchDefault">when default</li>' + '<li template="ngSwitchDefault">when default</li>' +
'</ul></div>'; '</ul></div>';
@ -70,10 +99,10 @@ export function main() {
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = '<div>' + var template = '<div>' +
'<ul [ngSwitch]="switchValue">' + '<ul [ngSwitch]="switchValue">' +
'<template ngSwitchWhen="a"><li>when a1;</li></template>' + '<template ngSwitchCase="a"><li>when a1;</li></template>' +
'<template ngSwitchWhen="b"><li>when b1;</li></template>' + '<template ngSwitchCase="b"><li>when b1;</li></template>' +
'<template ngSwitchWhen="a"><li>when a2;</li></template>' + '<template ngSwitchCase="a"><li>when a2;</li></template>' +
'<template ngSwitchWhen="b"><li>when b2;</li></template>' + '<template ngSwitchCase="b"><li>when b2;</li></template>' +
'<template ngSwitchDefault><li>when default1;</li></template>' + '<template ngSwitchDefault><li>when default1;</li></template>' +
'<template ngSwitchDefault><li>when default2;</li></template>' + '<template ngSwitchDefault><li>when default2;</li></template>' +
'</ul></div>'; '</ul></div>';
@ -105,8 +134,8 @@ export function main() {
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = '<div>' + var template = '<div>' +
'<ul [ngSwitch]="switchValue">' + '<ul [ngSwitch]="switchValue">' +
'<template [ngSwitchWhen]="when1"><li>when 1;</li></template>' + '<template [ngSwitchCase]="when1"><li>when 1;</li></template>' +
'<template [ngSwitchWhen]="when2"><li>when 2;</li></template>' + '<template [ngSwitchCase]="when2"><li>when 2;</li></template>' +
'<template ngSwitchDefault><li>when default;</li></template>' + '<template ngSwitchDefault><li>when default;</li></template>' +
'</ul></div>'; '</ul></div>';
@ -143,7 +172,7 @@ export function main() {
} }
@Component( @Component(
{selector: 'test-cmp', directives: [NgSwitch, NgSwitchWhen, NgSwitchDefault], template: ''}) {selector: 'test-cmp', directives: [NgSwitch, NgSwitchCase, NgSwitchDefault], template: ''})
class TestComponent { class TestComponent {
switchValue: any; switchValue: any;
when1: any; when1: any;

View File

@ -980,11 +980,12 @@ const COMMON = [
'NgStyle.rawStyle=(v:{[key:string]:string})', 'NgStyle.rawStyle=(v:{[key:string]:string})',
'NgSwitch', 'NgSwitch',
'NgSwitch.ngSwitch=(value:any)', 'NgSwitch.ngSwitch=(value:any)',
'NgSwitchCase',
'NgSwitchCase.constructor(viewContainer:ViewContainerRef, templateRef:TemplateRef<Object>, ngSwitch:NgSwitch)',
'NgSwitchCase.ngSwitchCase=(value:any)',
'NgSwitchCase.ngSwitchWhen=(value:any)',
'NgSwitchDefault', 'NgSwitchDefault',
'NgSwitchDefault.constructor(viewContainer:ViewContainerRef, templateRef:TemplateRef<Object>, sswitch:NgSwitch)', 'NgSwitchDefault.constructor(viewContainer:ViewContainerRef, templateRef:TemplateRef<Object>, sswitch:NgSwitch)',
'NgSwitchWhen',
'NgSwitchWhen.constructor(viewContainer:ViewContainerRef, templateRef:TemplateRef<Object>, ngSwitch:NgSwitch)',
'NgSwitchWhen.ngSwitchWhen=(value:any)',
'NgTemplateOutlet', 'NgTemplateOutlet',
'NgTemplateOutlet.constructor(_viewContainerRef:ViewContainerRef)', 'NgTemplateOutlet.constructor(_viewContainerRef:ViewContainerRef)',
'NgTemplateOutlet.ngTemplateOutlet=(templateRef:TemplateRef<Object>)', 'NgTemplateOutlet.ngTemplateOutlet=(templateRef:TemplateRef<Object>)',