feat(ivy): support for the ngForOf directive, with tests (#21430)

Implement NgOnChangesFeature, ViewContainerRef, TemplateRef,
and the renderEmbeddedTemplate instruction, and wire together the
pieces required for the ngForOf directive to work.

PR Close #21430
This commit is contained in:
Alex Rickabaugh
2018-01-17 10:09:05 -08:00
committed by Miško Hevery
parent 6472661ae8
commit 0ad02de47e
13 changed files with 456 additions and 56 deletions

View File

@ -6,13 +6,15 @@
* found in the LICENSE file at https://angular.io/license
*/
import {SimpleChange} from '../change_detection/change_detection_util';
import {OnChanges, SimpleChanges} from '../metadata/lifecycle_hooks';
import {RendererType2} from '../render/api';
import {Type} from '../type';
import {resolveRendererType2} from '../view/util';
import {diPublic} from './di';
import {componentRefresh} from './instructions';
import {ComponentDef, ComponentDefArgs, DirectiveDef, DirectiveDefArgs} from './interfaces/definition';
import {ComponentDef, ComponentDefArgs, DirectiveDef, DirectiveDefArgs, TypedDirectiveDef} from './interfaces/definition';
@ -54,8 +56,57 @@ export function defineComponent<T>(componentDefinition: ComponentDefArgs<T>): Co
return def;
}
export function NgOnChangesFeature<T>(definition: DirectiveDef<T>) {
// TODO: implement. See: https://app.asana.com/0/443577627818617/465170715764659
const PRIVATE_PREFIX = '__ngOnChanges_';
type OnChangesExpando = OnChanges & {
__ngOnChanges_: SimpleChanges|null|undefined;
[key: string]: any;
};
export function NgOnChangesFeature<T>(type: Type<T>): (definition: DirectiveDef<any>) => void {
return function(definition: DirectiveDef<any>): void {
const inputs = definition.inputs;
const proto = type.prototype;
// Place where we will store SimpleChanges if there is a change
Object.defineProperty(proto, PRIVATE_PREFIX, {value: undefined, writable: true});
for (let pubKey in inputs) {
const minKey = inputs[pubKey];
const privateMinKey = PRIVATE_PREFIX + minKey;
// Create a place where the actual value will be stored and make it non-enumerable
Object.defineProperty(proto, privateMinKey, {value: undefined, writable: true});
const existingDesc = Object.getOwnPropertyDescriptor(proto, minKey);
// create a getter and setter for property
Object.defineProperty(proto, minKey, {
get: function(this: OnChangesExpando) {
return (existingDesc && existingDesc.get) ? existingDesc.get.call(this) :
this[privateMinKey];
},
set: function(this: OnChangesExpando, value: any) {
let simpleChanges = this[PRIVATE_PREFIX];
let isFirstChange = simpleChanges === undefined;
if (simpleChanges == null) {
simpleChanges = this[PRIVATE_PREFIX] = {};
}
simpleChanges[pubKey] = new SimpleChange(this[privateMinKey], value, isFirstChange);
(existingDesc && existingDesc.set) ? existingDesc.set.call(this, value) :
this[privateMinKey] = value;
}
});
}
proto.ngDoCheck = (function(delegateDoCheck) {
return function(this: OnChangesExpando) {
let simpleChanges = this[PRIVATE_PREFIX];
if (simpleChanges != null) {
this.ngOnChanges(simpleChanges);
this[PRIVATE_PREFIX] = null;
}
delegateDoCheck && delegateDoCheck.apply(this);
};
})(proto.ngDoCheck);
};
}
export function PublicFeature<T>(definition: DirectiveDef<T>) {