chore: fix up ngClass for types/export missing public API

Closes #7202
This commit is contained in:
Misko Hevery 2016-02-20 08:52:51 -08:00 committed by Miško Hevery
parent 5a59e44765
commit 6402d61f69
7 changed files with 118 additions and 79 deletions

View File

@ -1,14 +1,16 @@
import {isPresent, isString, StringWrapper, isBlank, isArray} from 'angular2/src/facade/lang'; import {isPresent, isString, isArray} from 'angular2/src/facade/lang';
import { import {
DoCheck, DoCheck,
OnDestroy, OnDestroy,
Directive, Directive,
ElementRef, ElementRef,
IterableDiffer,
IterableDiffers, IterableDiffers,
KeyValueDiffer,
KeyValueDiffers, KeyValueDiffers,
Renderer Renderer,
IterableDiffer,
KeyValueDiffer,
CollectionChangeRecord,
KeyValueChangeRecord
} from 'angular2/core'; } from 'angular2/core';
import {StringMapWrapper, isListLikeIterable} from 'angular2/src/facade/collection'; import {StringMapWrapper, isListLikeIterable} from 'angular2/src/facade/collection';
@ -73,66 +75,68 @@ import {StringMapWrapper, isListLikeIterable} from 'angular2/src/facade/collecti
*/ */
@Directive({selector: '[ngClass]', inputs: ['rawClass: ngClass', 'initialClasses: class']}) @Directive({selector: '[ngClass]', inputs: ['rawClass: ngClass', 'initialClasses: class']})
export class NgClass implements DoCheck, OnDestroy { export class NgClass implements DoCheck, OnDestroy {
private _differ: any; private _iterableDiffer: IterableDiffer;
private _mode: string; private _keyValueDiffer: KeyValueDiffer;
private _initialClasses = []; private _initialClasses: string[] = [];
private _rawClass; private _rawClass: string[] | Set<string>;
constructor(private _iterableDiffers: IterableDiffers, private _keyValueDiffers: KeyValueDiffers, constructor(private _iterableDiffers: IterableDiffers, private _keyValueDiffers: KeyValueDiffers,
private _ngEl: ElementRef, private _renderer: Renderer) {} private _ngEl: ElementRef, private _renderer: Renderer) {}
set initialClasses(v) { set initialClasses(v: string) {
this._applyInitialClasses(true); this._applyInitialClasses(true);
this._initialClasses = isPresent(v) && isString(v) ? v.split(' ') : []; this._initialClasses = isPresent(v) && isString(v) ? v.split(' ') : [];
this._applyInitialClasses(false); this._applyInitialClasses(false);
this._applyClasses(this._rawClass, false); this._applyClasses(this._rawClass, false);
} }
set rawClass(v) { set rawClass(v: string | string[] | Set<string>| {[key: string]: any}) {
this._cleanupClasses(this._rawClass); this._cleanupClasses(this._rawClass);
if (isString(v)) { if (isString(v)) {
v = v.split(' '); v = (<string>v).split(' ');
} }
this._rawClass = v; this._rawClass = <string[] | Set<string>>v;
this._iterableDiffer = null;
this._keyValueDiffer = null;
if (isPresent(v)) { if (isPresent(v)) {
if (isListLikeIterable(v)) { if (isListLikeIterable(v)) {
this._differ = this._iterableDiffers.find(v).create(null); this._iterableDiffer = this._iterableDiffers.find(v).create(null);
this._mode = 'iterable';
} else { } else {
this._differ = this._keyValueDiffers.find(v).create(null); this._keyValueDiffer = this._keyValueDiffers.find(v).create(null);
this._mode = 'keyValue';
} }
} else {
this._differ = null;
} }
} }
ngDoCheck(): void { ngDoCheck(): void {
if (isPresent(this._differ)) { if (isPresent(this._iterableDiffer)) {
var changes = this._differ.diff(this._rawClass); var changes = this._iterableDiffer.diff(this._rawClass);
if (isPresent(changes)) { if (isPresent(changes)) {
if (this._mode == 'iterable') {
this._applyIterableChanges(changes); this._applyIterableChanges(changes);
} else {
this._applyKeyValueChanges(changes);
} }
} }
if (isPresent(this._keyValueDiffer)) {
var changes = this._keyValueDiffer.diff(this._rawClass);
if (isPresent(changes)) {
this._applyKeyValueChanges(changes);
}
} }
} }
ngOnDestroy(): void { this._cleanupClasses(this._rawClass); } ngOnDestroy(): void { this._cleanupClasses(this._rawClass); }
private _cleanupClasses(rawClassVal): void { private _cleanupClasses(rawClassVal: string[] | Set<string>| {[key: string]: any}): void {
this._applyClasses(rawClassVal, true); this._applyClasses(rawClassVal, true);
this._applyInitialClasses(false); this._applyInitialClasses(false);
} }
private _applyKeyValueChanges(changes: any): void { private _applyKeyValueChanges(changes: any): void {
changes.forEachAddedItem((record) => { this._toggleClass(record.key, record.currentValue); }); changes.forEachAddedItem(
changes.forEachChangedItem((record) => { this._toggleClass(record.key, record.currentValue); }); (record: KeyValueChangeRecord) => { this._toggleClass(record.key, record.currentValue); });
changes.forEachRemovedItem((record) => { changes.forEachChangedItem(
(record: KeyValueChangeRecord) => { this._toggleClass(record.key, record.currentValue); });
changes.forEachRemovedItem((record: KeyValueChangeRecord) => {
if (record.previousValue) { if (record.previousValue) {
this._toggleClass(record.key, false); this._toggleClass(record.key, false);
} }
@ -140,15 +144,17 @@ export class NgClass implements DoCheck, OnDestroy {
} }
private _applyIterableChanges(changes: any): void { private _applyIterableChanges(changes: any): void {
changes.forEachAddedItem((record) => { this._toggleClass(record.item, true); }); changes.forEachAddedItem(
changes.forEachRemovedItem((record) => { this._toggleClass(record.item, false); }); (record: CollectionChangeRecord) => { this._toggleClass(record.item, true); });
changes.forEachRemovedItem(
(record: CollectionChangeRecord) => { this._toggleClass(record.item, false); });
} }
private _applyInitialClasses(isCleanup: boolean) { private _applyInitialClasses(isCleanup: boolean) {
this._initialClasses.forEach(className => this._toggleClass(className, !isCleanup)); this._initialClasses.forEach(className => this._toggleClass(className, !isCleanup));
} }
private _applyClasses(rawClassVal: string[] | Set<string>| {[key: string]: string}, private _applyClasses(rawClassVal: string[] | Set<string>| {[key: string]: any},
isCleanup: boolean) { isCleanup: boolean) {
if (isPresent(rawClassVal)) { if (isPresent(rawClassVal)) {
if (isArray(rawClassVal)) { if (isArray(rawClassVal)) {
@ -156,14 +162,15 @@ export class NgClass implements DoCheck, OnDestroy {
} else if (rawClassVal instanceof Set) { } else if (rawClassVal instanceof Set) {
(<Set<string>>rawClassVal).forEach(className => this._toggleClass(className, !isCleanup)); (<Set<string>>rawClassVal).forEach(className => this._toggleClass(className, !isCleanup));
} else { } else {
StringMapWrapper.forEach(<{[k: string]: string}>rawClassVal, (expVal, className) => { StringMapWrapper.forEach(<{[k: string]: any}>rawClassVal,
if (expVal) this._toggleClass(className, !isCleanup); (expVal: any, className: string) => {
if (isPresent(expVal)) this._toggleClass(className, !isCleanup);
}); });
} }
} }
} }
private _toggleClass(className: string, enabled): void { private _toggleClass(className: string, enabled: boolean): void {
className = className.trim(); className = className.trim();
if (className.length > 0) { if (className.length > 0) {
if (className.indexOf(' ') > -1) { if (className.indexOf(' ') > -1) {

View File

@ -7,7 +7,7 @@ import {
Renderer Renderer
} from 'angular2/core'; } from 'angular2/core';
import {isPresent, isBlank, print} from 'angular2/src/facade/lang'; import {isPresent, isBlank, print} from 'angular2/src/facade/lang';
import {KVChangeRecord} from "../../core/change_detection/differs/default_keyvalue_differ"; import {KeyValueChangeRecord} from "../../core/change_detection/differs/default_keyvalue_differ";
/** /**
* The `NgStyle` directive changes styles based on a result of expression evaluation. * The `NgStyle` directive changes styles based on a result of expression evaluation.
@ -88,10 +88,11 @@ export class NgStyle implements DoCheck {
private _applyChanges(changes: any): void { private _applyChanges(changes: any): void {
changes.forEachAddedItem( changes.forEachAddedItem(
(record: KVChangeRecord) => { this._setStyle(record.key, record.currentValue); }); (record: KeyValueChangeRecord) => { this._setStyle(record.key, record.currentValue); });
changes.forEachChangedItem( changes.forEachChangedItem(
(record: KVChangeRecord) => { this._setStyle(record.key, record.currentValue); }); (record: KeyValueChangeRecord) => { this._setStyle(record.key, record.currentValue); });
changes.forEachRemovedItem((record: KVChangeRecord) => { this._setStyle(record.key, null); }); changes.forEachRemovedItem(
(record: KeyValueChangeRecord) => { this._setStyle(record.key, null); });
} }
private _setStyle(name: string, val: string): void { private _setStyle(name: string, val: string): void {

View File

@ -21,5 +21,7 @@ export {
KeyValueDiffers, KeyValueDiffers,
KeyValueDiffer, KeyValueDiffer,
KeyValueDifferFactory, KeyValueDifferFactory,
CollectionChangeRecord,
KeyValueChangeRecord,
TrackByFn TrackByFn
} from './change_detection/change_detection'; } from './change_detection/change_detection';

View File

@ -1,9 +1,20 @@
import {IterableDiffers, IterableDifferFactory, TrackByFn} from './differs/iterable_differs'; import {IterableDiffers, IterableDifferFactory} from './differs/iterable_differs';
import {DefaultIterableDifferFactory} from './differs/default_iterable_differ'; import {DefaultIterableDifferFactory} from './differs/default_iterable_differ';
import {KeyValueDiffers, KeyValueDifferFactory} from './differs/keyvalue_differs'; import {KeyValueDiffers, KeyValueDifferFactory} from './differs/keyvalue_differs';
import {DefaultKeyValueDifferFactory} from './differs/default_keyvalue_differ'; import {
import {CONST, CONST_EXPR, isPresent} from 'angular2/src/facade/lang'; DefaultKeyValueDifferFactory,
KeyValueChangeRecord
} from './differs/default_keyvalue_differ';
import {CONST_EXPR} from 'angular2/src/facade/lang';
export {
DefaultKeyValueDifferFactory,
KeyValueChangeRecord
} from './differs/default_keyvalue_differ';
export {
DefaultIterableDifferFactory,
CollectionChangeRecord
} from './differs/default_iterable_differ';
export { export {
ASTWithSource, ASTWithSource,
AST, AST,

View File

@ -13,14 +13,14 @@ export class DefaultKeyValueDifferFactory implements KeyValueDifferFactory {
export class DefaultKeyValueDiffer implements KeyValueDiffer { export class DefaultKeyValueDiffer implements KeyValueDiffer {
private _records: Map<any, any> = new Map(); private _records: Map<any, any> = new Map();
private _mapHead: KVChangeRecord = null; private _mapHead: KeyValueChangeRecord = null;
private _previousMapHead: KVChangeRecord = null; private _previousMapHead: KeyValueChangeRecord = null;
private _changesHead: KVChangeRecord = null; private _changesHead: KeyValueChangeRecord = null;
private _changesTail: KVChangeRecord = null; private _changesTail: KeyValueChangeRecord = null;
private _additionsHead: KVChangeRecord = null; private _additionsHead: KeyValueChangeRecord = null;
private _additionsTail: KVChangeRecord = null; private _additionsTail: KeyValueChangeRecord = null;
private _removalsHead: KVChangeRecord = null; private _removalsHead: KeyValueChangeRecord = null;
private _removalsTail: KVChangeRecord = null; private _removalsTail: KeyValueChangeRecord = null;
get isDirty(): boolean { get isDirty(): boolean {
return this._additionsHead !== null || this._changesHead !== null || return this._additionsHead !== null || this._changesHead !== null ||
@ -28,35 +28,35 @@ export class DefaultKeyValueDiffer implements KeyValueDiffer {
} }
forEachItem(fn: Function) { forEachItem(fn: Function) {
var record: KVChangeRecord; var record: KeyValueChangeRecord;
for (record = this._mapHead; record !== null; record = record._next) { for (record = this._mapHead; record !== null; record = record._next) {
fn(record); fn(record);
} }
} }
forEachPreviousItem(fn: Function) { forEachPreviousItem(fn: Function) {
var record: KVChangeRecord; var record: KeyValueChangeRecord;
for (record = this._previousMapHead; record !== null; record = record._nextPrevious) { for (record = this._previousMapHead; record !== null; record = record._nextPrevious) {
fn(record); fn(record);
} }
} }
forEachChangedItem(fn: Function) { forEachChangedItem(fn: Function) {
var record: KVChangeRecord; var record: KeyValueChangeRecord;
for (record = this._changesHead; record !== null; record = record._nextChanged) { for (record = this._changesHead; record !== null; record = record._nextChanged) {
fn(record); fn(record);
} }
} }
forEachAddedItem(fn: Function) { forEachAddedItem(fn: Function) {
var record: KVChangeRecord; var record: KeyValueChangeRecord;
for (record = this._additionsHead; record !== null; record = record._nextAdded) { for (record = this._additionsHead; record !== null; record = record._nextAdded) {
fn(record); fn(record);
} }
} }
forEachRemovedItem(fn: Function) { forEachRemovedItem(fn: Function) {
var record: KVChangeRecord; var record: KeyValueChangeRecord;
for (record = this._removalsHead; record !== null; record = record._nextRemoved) { for (record = this._removalsHead; record !== null; record = record._nextRemoved) {
fn(record); fn(record);
} }
@ -80,9 +80,9 @@ export class DefaultKeyValueDiffer implements KeyValueDiffer {
check(map: Map<any, any>): boolean { check(map: Map<any, any>): boolean {
this._reset(); this._reset();
var records = this._records; var records = this._records;
var oldSeqRecord: KVChangeRecord = this._mapHead; var oldSeqRecord: KeyValueChangeRecord = this._mapHead;
var lastOldSeqRecord: KVChangeRecord = null; var lastOldSeqRecord: KeyValueChangeRecord = null;
var lastNewSeqRecord: KVChangeRecord = null; var lastNewSeqRecord: KeyValueChangeRecord = null;
var seqChanged: boolean = false; var seqChanged: boolean = false;
this._forEach(map, (value, key) => { this._forEach(map, (value, key) => {
@ -104,7 +104,7 @@ export class DefaultKeyValueDiffer implements KeyValueDiffer {
if (records.has(key)) { if (records.has(key)) {
newSeqRecord = records.get(key); newSeqRecord = records.get(key);
} else { } else {
newSeqRecord = new KVChangeRecord(key); newSeqRecord = new KeyValueChangeRecord(key);
records.set(key, newSeqRecord); records.set(key, newSeqRecord);
newSeqRecord.currentValue = value; newSeqRecord.currentValue = value;
this._addToAdditions(newSeqRecord); this._addToAdditions(newSeqRecord);
@ -132,7 +132,7 @@ export class DefaultKeyValueDiffer implements KeyValueDiffer {
/** @internal */ /** @internal */
_reset() { _reset() {
if (this.isDirty) { if (this.isDirty) {
var record: KVChangeRecord; var record: KeyValueChangeRecord;
// Record the state of the mapping // Record the state of the mapping
for (record = this._previousMapHead = this._mapHead; record !== null; record = record._next) { for (record = this._previousMapHead = this._mapHead; record !== null; record = record._next) {
record._nextPrevious = record._next; record._nextPrevious = record._next;
@ -178,7 +178,7 @@ export class DefaultKeyValueDiffer implements KeyValueDiffer {
} }
/** @internal */ /** @internal */
_truncate(lastRecord: KVChangeRecord, record: KVChangeRecord) { _truncate(lastRecord: KeyValueChangeRecord, record: KeyValueChangeRecord) {
while (record !== null) { while (record !== null) {
if (lastRecord === null) { if (lastRecord === null) {
this._mapHead = null; this._mapHead = null;
@ -196,7 +196,7 @@ export class DefaultKeyValueDiffer implements KeyValueDiffer {
record = nextRecord; record = nextRecord;
} }
for (var rec: KVChangeRecord = this._removalsHead; rec !== null; rec = rec._nextRemoved) { for (var rec: KeyValueChangeRecord = this._removalsHead; rec !== null; rec = rec._nextRemoved) {
rec.previousValue = rec.currentValue; rec.previousValue = rec.currentValue;
rec.currentValue = null; rec.currentValue = null;
this._records.delete(rec.key); this._records.delete(rec.key);
@ -204,13 +204,13 @@ export class DefaultKeyValueDiffer implements KeyValueDiffer {
} }
/** @internal */ /** @internal */
_isInRemovals(record: KVChangeRecord) { _isInRemovals(record: KeyValueChangeRecord) {
return record === this._removalsHead || record._nextRemoved !== null || return record === this._removalsHead || record._nextRemoved !== null ||
record._prevRemoved !== null; record._prevRemoved !== null;
} }
/** @internal */ /** @internal */
_addToRemovals(record: KVChangeRecord) { _addToRemovals(record: KeyValueChangeRecord) {
// todo(vicb) assert // todo(vicb) assert
// assert(record._next == null); // assert(record._next == null);
// assert(record._nextAdded == null); // assert(record._nextAdded == null);
@ -227,7 +227,7 @@ export class DefaultKeyValueDiffer implements KeyValueDiffer {
} }
/** @internal */ /** @internal */
_removeFromSeq(prev: KVChangeRecord, record: KVChangeRecord) { _removeFromSeq(prev: KeyValueChangeRecord, record: KeyValueChangeRecord) {
var next = record._next; var next = record._next;
if (prev === null) { if (prev === null) {
this._mapHead = next; this._mapHead = next;
@ -242,7 +242,7 @@ export class DefaultKeyValueDiffer implements KeyValueDiffer {
} }
/** @internal */ /** @internal */
_removeFromRemovals(record: KVChangeRecord) { _removeFromRemovals(record: KeyValueChangeRecord) {
// todo(vicb) assert // todo(vicb) assert
// assert(record._next == null); // assert(record._next == null);
// assert(record._nextAdded == null); // assert(record._nextAdded == null);
@ -264,7 +264,7 @@ export class DefaultKeyValueDiffer implements KeyValueDiffer {
} }
/** @internal */ /** @internal */
_addToAdditions(record: KVChangeRecord) { _addToAdditions(record: KeyValueChangeRecord) {
// todo(vicb): assert // todo(vicb): assert
// assert(record._next == null); // assert(record._next == null);
// assert(record._nextAdded == null); // assert(record._nextAdded == null);
@ -280,7 +280,7 @@ export class DefaultKeyValueDiffer implements KeyValueDiffer {
} }
/** @internal */ /** @internal */
_addToChanges(record: KVChangeRecord) { _addToChanges(record: KeyValueChangeRecord) {
// todo(vicb) assert // todo(vicb) assert
// assert(record._nextAdded == null); // assert(record._nextAdded == null);
// assert(record._nextChanged == null); // assert(record._nextChanged == null);
@ -300,7 +300,7 @@ export class DefaultKeyValueDiffer implements KeyValueDiffer {
var changes = []; var changes = [];
var additions = []; var additions = [];
var removals = []; var removals = [];
var record: KVChangeRecord; var record: KeyValueChangeRecord;
for (record = this._mapHead; record !== null; record = record._next) { for (record = this._mapHead; record !== null; record = record._next) {
items.push(stringify(record)); items.push(stringify(record));
@ -334,22 +334,22 @@ export class DefaultKeyValueDiffer implements KeyValueDiffer {
} }
export class KVChangeRecord { export class KeyValueChangeRecord {
previousValue: any = null; previousValue: any = null;
currentValue: any = null; currentValue: any = null;
/** @internal */ /** @internal */
_nextPrevious: KVChangeRecord = null; _nextPrevious: KeyValueChangeRecord = null;
/** @internal */ /** @internal */
_next: KVChangeRecord = null; _next: KeyValueChangeRecord = null;
/** @internal */ /** @internal */
_nextAdded: KVChangeRecord = null; _nextAdded: KeyValueChangeRecord = null;
/** @internal */ /** @internal */
_nextRemoved: KVChangeRecord = null; _nextRemoved: KeyValueChangeRecord = null;
/** @internal */ /** @internal */
_prevRemoved: KVChangeRecord = null; _prevRemoved: KeyValueChangeRecord = null;
/** @internal */ /** @internal */
_nextChanged: KVChangeRecord = null; _nextChanged: KeyValueChangeRecord = null;
constructor(public key: any) {} constructor(public key: any) {}

View File

@ -789,6 +789,7 @@ var NG_CORE = [
'ProviderBuilder.token', 'ProviderBuilder.token',
'ProviderBuilder.token=', 'ProviderBuilder.token=',
'PLATFORM_DIRECTIVES:js', 'PLATFORM_DIRECTIVES:js',
"CollectionChangeRecord",
'ChangeDetectionError', 'ChangeDetectionError',
'ChangeDetectionError.context', 'ChangeDetectionError.context',
'ChangeDetectionError.location', 'ChangeDetectionError.location',
@ -1152,6 +1153,13 @@ var NG_CORE = [
'Key.id=', 'Key.id=',
'Key.token', 'Key.token',
'Key.token=', 'Key.token=',
'KeyValueChangeRecord',
'KeyValueChangeRecord.currentValue',
'KeyValueChangeRecord.currentValue=',
'KeyValueChangeRecord.key',
'KeyValueChangeRecord.key=',
'KeyValueChangeRecord.previousValue',
'KeyValueChangeRecord.previousValue=',
'KeyValueDiffers#create()', 'KeyValueDiffers#create()',
'KeyValueDiffers#extend()', 'KeyValueDiffers#extend()',
'KeyValueDiffers', 'KeyValueDiffers',

View File

@ -80,6 +80,11 @@ const CORE = [
'ClassDefinition', 'ClassDefinition',
'ClassDefinition.constructor:Function|any[]', 'ClassDefinition.constructor:Function|any[]',
'ClassDefinition.extends:Type', 'ClassDefinition.extends:Type',
'CollectionChangeRecord',
'CollectionChangeRecord.constructor(item:any, trackById:any)',
'CollectionChangeRecord.currentIndex:number',
'CollectionChangeRecord.previousIndex:number',
'CollectionChangeRecord.toString():string',
'Compiler', 'Compiler',
'Compiler.clearCache():any', 'Compiler.clearCache():any',
'Compiler.compileInHost(componentType:Type):Promise<HostViewFactoryRef>', 'Compiler.compileInHost(componentType:Type):Promise<HostViewFactoryRef>',
@ -260,6 +265,11 @@ const CORE = [
'Key.displayName:string', 'Key.displayName:string',
'Key.get(token:Object):Key', 'Key.get(token:Object):Key',
'Key.numberOfKeys:number', 'Key.numberOfKeys:number',
'KeyValueChangeRecord',
'KeyValueChangeRecord.constructor(key:any)',
'KeyValueChangeRecord.currentValue:any',
'KeyValueChangeRecord.previousValue:any',
'KeyValueChangeRecord.toString():string',
'KeyValueDiffer', 'KeyValueDiffer',
'KeyValueDiffer.diff(object:any):any', 'KeyValueDiffer.diff(object:any):any',
'KeyValueDiffer.onDestroy():any', 'KeyValueDiffer.onDestroy():any',
@ -656,10 +666,10 @@ const COMMON = [
'MinLengthValidator.validate(c:Control):{[key:string]:any}', 'MinLengthValidator.validate(c:Control):{[key:string]:any}',
'NgClass', 'NgClass',
'NgClass.constructor(_iterableDiffers:IterableDiffers, _keyValueDiffers:KeyValueDiffers, _ngEl:ElementRef, _renderer:Renderer)', 'NgClass.constructor(_iterableDiffers:IterableDiffers, _keyValueDiffers:KeyValueDiffers, _ngEl:ElementRef, _renderer:Renderer)',
'NgClass.initialClasses=(v:any)', 'NgClass.initialClasses=(v:string)',
'NgClass.ngDoCheck():void', 'NgClass.ngDoCheck():void',
'NgClass.ngOnDestroy():void', 'NgClass.ngOnDestroy():void',
'NgClass.rawClass=(v:any)', 'NgClass.rawClass=(v:string|string[]|Set<string>|{[key:string]:any})',
'NgControl', 'NgControl',
'NgControl.asyncValidator:Function', 'NgControl.asyncValidator:Function',
'NgControl.name:string', 'NgControl.name:string',