feat(elements): George's comments (#22413)

PR Close #22413
This commit is contained in:
Andrew Seguin
2018-03-02 10:08:16 -08:00
committed by Miško Hevery
parent 19368085aa
commit 46efd4b938
22 changed files with 81 additions and 222 deletions

View File

@ -104,7 +104,7 @@ export class ComponentFactoryNgElementStrategy implements NgElementStrategy {
* Returns the component property value. If the component has not yet been created, the value is
* retrieved from the cached initialization values.
*/
getPropertyValue(property: string): any {
getInputValue(property: string): any {
if (!this.componentRef) {
return this.initialInputValues.get(property);
}
@ -116,8 +116,8 @@ export class ComponentFactoryNgElementStrategy implements NgElementStrategy {
* Sets the input value for the property. If the component has not yet been created, the value is
* cached and set when the component is created.
*/
setPropertyValue(property: string, value: any): void {
if (strictEquals(value, this.getPropertyValue(property))) {
setInputValue(property: string, value: any): void {
if (strictEquals(value, this.getInputValue(property))) {
return;
}
@ -158,7 +158,7 @@ export class ComponentFactoryNgElementStrategy implements NgElementStrategy {
this.componentFactory.inputs.forEach(({propName}) => {
const initialValue = this.initialInputValues.get(propName);
if (initialValue) {
this.setPropertyValue(propName, initialValue);
this.setInputValue(propName, initialValue);
} else {
// Keep track of inputs that were not initialized in case we need to know this for
// calling ngOnChanges with SimpleChanges
@ -185,8 +185,11 @@ export class ComponentFactoryNgElementStrategy implements NgElementStrategy {
return;
}
(this.componentRef !.instance as any as OnChanges).ngOnChanges(this.inputChanges);
// Cache the changes and set inputChanges to null to capture any changes that might occur
// during ngOnChanges.
const inputChanges = this.inputChanges;
this.inputChanges = null;
(this.componentRef !.instance as any as OnChanges).ngOnChanges(inputChanges);
}
/**
@ -199,8 +202,8 @@ export class ComponentFactoryNgElementStrategy implements NgElementStrategy {
}
this.scheduledChangeDetectionFn = scheduler.scheduleBeforeRender(() => {
this.detectChanges();
this.scheduledChangeDetectionFn = null;
this.detectChanges();
});
}
@ -209,7 +212,7 @@ export class ComponentFactoryNgElementStrategy implements NgElementStrategy {
*/
protected recordInputChange(property: string, currentValue: any): void {
// Do not record the change if the component does not implement `OnChanges`.
if (!this.componentRef || !this.implementsOnChanges) {
if (this.componentRef && !this.implementsOnChanges) {
return;
}
@ -228,7 +231,7 @@ export class ComponentFactoryNgElementStrategy implements NgElementStrategy {
const isFirstChange = this.uninitializedInputs.has(property);
this.uninitializedInputs.delete(property);
const previousValue = isFirstChange ? undefined : this.getPropertyValue(property);
const previousValue = isFirstChange ? undefined : this.getInputValue(property);
this.inputChanges[property] = new SimpleChange(previousValue, currentValue, isFirstChange);
}

View File

@ -29,8 +29,8 @@ export interface NgElementStrategy {
connect(element: HTMLElement): void;
disconnect(): void;
getPropertyValue(propName: string): any;
setPropertyValue(propName: string, value: string): void;
getInputValue(propName: string): any;
setInputValue(propName: string, value: string): void;
}
/**

View File

@ -42,6 +42,8 @@ export abstract class NgElement extends HTMLElement {
/**
* Additional type information that can be added to the NgElement class for properties added based
* on the inputs and methods of the underlying component.
*
* @experimental
*/
export type WithProperties<P> = {
[property in keyof P]: P[property]
@ -59,14 +61,14 @@ export interface NgElementConfig {
injector: Injector;
strategyFactory?: NgElementStrategyFactory;
propertyInputs?: string[];
attributeToPropertyInputs?: Map<string, string>;
attributeToPropertyInputs?: {[key: string]: string};
}
/** Gets a map of default set of attributes to observe and the properties they affect. */
function getDefaultAttributeToPropertyInputs(inputs: {propName: string, templateName: string}[]) {
const attributeToPropertyInputs = new Map<string, string>();
const attributeToPropertyInputs: {[key: string]: string} = {};
inputs.forEach(({propName, templateName}) => {
attributeToPropertyInputs.set(camelToDashCase(templateName), propName);
attributeToPropertyInputs[camelToDashCase(templateName)] = propName;
});
return attributeToPropertyInputs;
@ -100,7 +102,7 @@ export function createNgElementConstructor<P>(
config.attributeToPropertyInputs || getDefaultAttributeToPropertyInputs(inputs);
class NgElementImpl extends NgElement {
static readonly observedAttributes = Array.from(attributeToPropertyInputs.keys());
static readonly observedAttributes = Object.keys(attributeToPropertyInputs);
constructor(strategyFactoryOverride?: NgElementStrategyFactory) {
super();
@ -113,16 +115,16 @@ export function createNgElementConstructor<P>(
attributeChangedCallback(
attrName: string, oldValue: string|null, newValue: string, namespace?: string): void {
const propName = attributeToPropertyInputs.get(attrName) !;
this.ngElementStrategy.setPropertyValue(propName, newValue);
const propName = attributeToPropertyInputs[attrName] !;
this.ngElementStrategy.setInputValue(propName, newValue);
}
connectedCallback(): void {
// Take element attribute inputs and set them as inputs on the strategy
attributeToPropertyInputs.forEach((propName, attrName) => {
const value = this.getAttribute(attrName);
if (value) {
this.ngElementStrategy.setPropertyValue(propName, value);
NgElementImpl.observedAttributes.forEach(attrName => {
const propName = attributeToPropertyInputs[attrName] !;
if (this.hasAttribute(attrName)) {
this.ngElementStrategy.setInputValue(propName, this.getAttribute(attrName) !);
}
});
@ -150,8 +152,8 @@ export function createNgElementConstructor<P>(
const propertyInputs = config.propertyInputs || inputs.map(({propName}) => propName);
propertyInputs.forEach(property => {
Object.defineProperty(NgElementImpl.prototype, property, {
get: function() { return this.ngElementStrategy.getPropertyValue(property); },
set: function(newValue: any) { this.ngElementStrategy.setPropertyValue(property, newValue); },
get: function() { return this.ngElementStrategy.getInputValue(property); },
set: function(newValue: any) { this.ngElementStrategy.setInputValue(property, newValue); },
configurable: true,
enumerable: true,
});

View File

@ -6,12 +6,6 @@
* found in the LICENSE file at https://angular.io/license
*/
/**
* @module
* @description
* Entry point for all public APIs of the common package.
*/
import {Version} from '@angular/core';
/**
* @experimental