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 {NgLocalization, NgPlural, NgPluralCase} from './directives/ng_plural';
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';

View File

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

View File

@ -3,7 +3,7 @@ import {Directive, Host, TemplateRef, ViewContainerRef} from '@angular/core';
import {ListWrapper, Map} from '../facade/collection';
import {isBlank, isPresent, normalizeBlank} from '../facade/lang';
const _WHEN_DEFAULT = /*@ts2dart_const*/ new Object();
const _CASE_DEFAULT = /*@ts2dart_const*/ new Object();
export class SwitchView {
constructor(
@ -17,17 +17,17 @@ export class SwitchView {
/**
* 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.
*
* `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
* (where you place the directive with a switch expression on the
* `[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
* expression is evaluated. If a matching expression is not found via a `ngSwitchWhen` property
* 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 `ngSwitchCase` property
* then an element with the `ngSwitchDefault` attribute is displayed.
*
* ### Example ([live demo](http://plnkr.co/edit/DQMTII95CbuqWrl3lYAs?p=preview))
@ -40,24 +40,24 @@ export class SwitchView {
* <button (click)="inc()">Increment</button>
*
* <div [ngSwitch]="value">
* <p *ngSwitchWhen="'init'">increment to start</p>
* <p *ngSwitchWhen="0">0, increment again</p>
* <p *ngSwitchWhen="1">1, increment again</p>
* <p *ngSwitchWhen="2">2, stop incrementing</p>
* <p *ngSwitchCase="'init'">increment to start</p>
* <p *ngSwitchCase="0">0, increment again</p>
* <p *ngSwitchCase="1">1, increment again</p>
* <p *ngSwitchCase="2">2, stop incrementing</p>
* <p *ngSwitchDefault>&gt; 2, STOP!</p>
* </div>
*
* <!-- alternate syntax -->
*
* <p [ngSwitch]="value">
* <template ngSwitchWhen="init">increment to start</template>
* <template [ngSwitchWhen]="0">0, increment again</template>
* <template [ngSwitchWhen]="1">1, increment again</template>
* <template [ngSwitchWhen]="2">2, stop incrementing</template>
* <template ngSwitchCase="init">increment to start</template>
* <template [ngSwitchCase]="0">0, increment again</template>
* <template [ngSwitchCase]="1">1, increment again</template>
* <template [ngSwitchCase]="2">2, stop incrementing</template>
* <template ngSwitchDefault>&gt; 2, STOP!</template>
* </p>
* `,
* directives: [NgSwitch, NgSwitchWhen, NgSwitchDefault]
* directives: [NgSwitch, ngSwitchCase, NgSwitchDefault]
* })
* export class App {
* value = 'init';
@ -88,7 +88,7 @@ export class NgSwitch {
var views = this._valueViews.get(value);
if (isBlank(views)) {
this._useDefault = true;
views = normalizeBlank(this._valueViews.get(_WHEN_DEFAULT));
views = normalizeBlank(this._valueViews.get(_CASE_DEFAULT));
}
this._activateViews(views);
@ -96,14 +96,14 @@ export class NgSwitch {
}
/** @internal */
_onWhenValueChanged(oldWhen: any, newWhen: any, view: SwitchView): void {
this._deregisterView(oldWhen, view);
this._registerView(newWhen, view);
_onCaseValueChanged(oldCase: any, newCase: any, view: SwitchView): void {
this._deregisterView(oldCase, view);
this._registerView(newCase, view);
if (oldWhen === this._switchValue) {
if (oldCase === this._switchValue) {
view.destroy();
ListWrapper.remove(this._activeViews, view);
} else if (newWhen === this._switchValue) {
} else if (newCase === this._switchValue) {
if (this._useDefault) {
this._useDefault = false;
this._emptyAllActiveViews();
@ -115,7 +115,7 @@ export class NgSwitch {
// Switch to default when there is no more active ViewContainers
if (this._activeViews.length === 0 && !this._useDefault) {
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 */
_deregisterView(value: any, view: SwitchView): void {
// `_WHEN_DEFAULT` is used a marker for non-registered whens
if (value === _WHEN_DEFAULT) return;
// `_CASE_DEFAULT` is used a marker for non-registered cases
if (value === _CASE_DEFAULT) return;
var views = this._valueViews.get(value);
if (views.length == 1) {
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.
*
* If multiple match expression match the switch expression value, all of them are displayed.
@ -172,13 +172,16 @@ export class NgSwitch {
*
* @experimental
*/
@Directive({selector: '[ngSwitchWhen]', inputs: ['ngSwitchWhen']})
export class NgSwitchWhen {
// `_WHEN_DEFAULT` is used as a marker for a not yet initialized value
@Directive({selector: '[ngSwitchCase],[ngSwitchWhen]', inputs: ['ngSwitchCase', 'ngSwitchWhen']})
export class NgSwitchCase {
// `_CASE_DEFAULT` is used as a marker for a not yet initialized value
/** @internal */
_value: any = _WHEN_DEFAULT;
_value: any = _CASE_DEFAULT;
/** @internal */
_view: SwitchView;
// TODO: remove when fully deprecated
/** @internal */
_warned: boolean;
private _switch: NgSwitch;
constructor(
@ -188,8 +191,17 @@ export class NgSwitchWhen {
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) {
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;
}
}
@ -207,6 +219,6 @@ export class NgSwitchDefault {
constructor(
viewContainer: ViewContainerRef, templateRef: TemplateRef<Object>,
@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 {TestComponentBuilder, ComponentFixture} from '@angular/compiler/testing';
import {NgSwitch, NgSwitchWhen, NgSwitchDefault} from '@angular/common';
import {NgSwitch, NgSwitchCase, NgSwitchDefault} from '@angular/common';
export function main() {
describe('switch', () => {
describe('switch value changes', () => {
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(
[TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
@ -42,7 +71,7 @@ export function main() {
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = '<div>' +
'<ul [ngSwitch]="switchValue">' +
'<li template="ngSwitchWhen \'a\'">when a</li>' +
'<li template="ngSwitchCase \'a\'">when a</li>' +
'<li template="ngSwitchDefault">when default</li>' +
'</ul></div>';
@ -70,10 +99,10 @@ export function main() {
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = '<div>' +
'<ul [ngSwitch]="switchValue">' +
'<template ngSwitchWhen="a"><li>when a1;</li></template>' +
'<template ngSwitchWhen="b"><li>when b1;</li></template>' +
'<template ngSwitchWhen="a"><li>when a2;</li></template>' +
'<template ngSwitchWhen="b"><li>when b2;</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>' +
'<template ngSwitchDefault><li>when default1;</li></template>' +
'<template ngSwitchDefault><li>when default2;</li></template>' +
'</ul></div>';
@ -105,8 +134,8 @@ export function main() {
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = '<div>' +
'<ul [ngSwitch]="switchValue">' +
'<template [ngSwitchWhen]="when1"><li>when 1;</li></template>' +
'<template [ngSwitchWhen]="when2"><li>when 2;</li></template>' +
'<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>';
@ -143,7 +172,7 @@ export function main() {
}
@Component(
{selector: 'test-cmp', directives: [NgSwitch, NgSwitchWhen, NgSwitchDefault], template: ''})
{selector: 'test-cmp', directives: [NgSwitch, NgSwitchCase, NgSwitchDefault], template: ''})
class TestComponent {
switchValue: any;
when1: any;

View File

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