feat(render): don’t use the reflector for setting properties

BREAKING CHANGES:
- host actions don't take an expression as value any more but only a method name,
  and assumes to get an array via the EventEmitter with the method arguments.
- Renderer.setElementProperty does not take `style.`/... prefixes any more.
  Use the new methods `Renderer.setElementAttribute`, ... instead

Part of #2476
Closes #2637
This commit is contained in:
Tobias Bosch
2015-06-18 15:44:44 -07:00
parent 2932377769
commit 0a51ccbd68
32 changed files with 643 additions and 568 deletions

View File

@ -6,9 +6,9 @@ import {List, StringMap} from 'angular2/src/facade/collection';
import * as viewModule from './view';
export class ElementBinder {
// updated later when events are bound
nestedProtoView: viewModule.AppProtoView = null;
// updated later, so we are able to resolve cycles
nestedProtoView: viewModule.AppProtoView = null;
// updated later when events are bound
hostListeners: StringMap<string, Map<number, AST>> = null;
constructor(public index: int, public parent: ElementBinder, public distanceToParent: int,

View File

@ -315,13 +315,13 @@ export class EventEmitterAccessor {
}
export class HostActionAccessor {
constructor(public actionExpression: string, public getter: Function) {}
constructor(public methodName: string, public getter: Function) {}
subscribe(view: viewModule.AppView, boundElementIndex: number, directive: Object) {
var eventEmitter = this.getter(directive);
return ObservableWrapper.subscribe(
eventEmitter,
actionObj => view.callAction(boundElementIndex, this.actionExpression, actionObj));
actionArgs => view.invokeElementMethod(boundElementIndex, this.methodName, actionArgs));
}
}

View File

@ -66,9 +66,20 @@ class BindingRecordsCreator {
_createElementPropertyRecords(bindings: List<BindingRecord>, boundElementIndex: number,
renderElementBinder: renderApi.ElementBinder) {
MapWrapper.forEach(renderElementBinder.propertyBindings, (astWithSource, propertyName) => {
bindings.push(BindingRecord.createForElement(astWithSource, boundElementIndex, propertyName));
ListWrapper.forEach(renderElementBinder.propertyBindings, (binding) => {
if (binding.type === renderApi.PropertyBindingType.PROPERTY) {
bindings.push(BindingRecord.createForElementProperty(binding.astWithSource,
boundElementIndex, binding.property));
} else if (binding.type === renderApi.PropertyBindingType.ATTRIBUTE) {
bindings.push(BindingRecord.createForElementAttribute(binding.astWithSource,
boundElementIndex, binding.property));
} else if (binding.type === renderApi.PropertyBindingType.CLASS) {
bindings.push(BindingRecord.createForElementClass(binding.astWithSource, boundElementIndex,
binding.property));
} else if (binding.type === renderApi.PropertyBindingType.STYLE) {
bindings.push(BindingRecord.createForElementStyle(binding.astWithSource, boundElementIndex,
binding.property, binding.unit));
}
});
}
@ -103,10 +114,21 @@ class BindingRecordsCreator {
for (var i = 0; i < directiveBinders.length; i++) {
var directiveBinder = directiveBinders[i];
// host properties
MapWrapper.forEach(directiveBinder.hostPropertyBindings, (astWithSource, propertyName) => {
ListWrapper.forEach(directiveBinder.hostPropertyBindings, (binding) => {
var dirIndex = new DirectiveIndex(boundElementIndex, i);
bindings.push(BindingRecord.createForHostProperty(dirIndex, astWithSource, propertyName));
if (binding.type === renderApi.PropertyBindingType.PROPERTY) {
bindings.push(BindingRecord.createForHostProperty(dirIndex, binding.astWithSource,
binding.property));
} else if (binding.type === renderApi.PropertyBindingType.ATTRIBUTE) {
bindings.push(BindingRecord.createForHostAttribute(dirIndex, binding.astWithSource,
binding.property));
} else if (binding.type === renderApi.PropertyBindingType.CLASS) {
bindings.push(
BindingRecord.createForHostClass(dirIndex, binding.astWithSource, binding.property));
} else if (binding.type === renderApi.PropertyBindingType.STYLE) {
bindings.push(BindingRecord.createForHostStyle(dirIndex, binding.astWithSource,
binding.property, binding.unit));
}
});
}
}

View File

@ -99,11 +99,20 @@ export class AppView implements ChangeDispatcher, EventDispatcher {
// dispatch to element injector or text nodes based on context
notifyOnBinding(b: BindingRecord, currentValue: any): void {
if (b.isElement()) {
if (b.isElementProperty()) {
this.renderer.setElementProperty(this.render, b.elementIndex, b.propertyName, currentValue);
} else {
// we know it refers to _textNodes.
} else if (b.isElementAttribute()) {
this.renderer.setElementAttribute(this.render, b.elementIndex, b.propertyName, currentValue);
} else if (b.isElementClass()) {
this.renderer.setElementClass(this.render, b.elementIndex, b.propertyName, currentValue);
} else if (b.isElementStyle()) {
var unit = isPresent(b.propertyUnit) ? b.propertyUnit : '';
this.renderer.setElementStyle(this.render, b.elementIndex, b.propertyName,
`${currentValue}${unit}`);
} else if (b.isTextNode()) {
this.renderer.setText(this.render, b.elementIndex, currentValue);
} else {
throw new BaseException('Unsupported directive record');
}
}
@ -124,8 +133,8 @@ export class AppView implements ChangeDispatcher, EventDispatcher {
return isPresent(childView) ? childView.changeDetector : null;
}
callAction(elementIndex: number, actionExpression: string, action: Object) {
this.renderer.callAction(this.render, elementIndex, actionExpression, action);
invokeElementMethod(elementIndex: number, methodName: string, args: List<any>) {
this.renderer.invokeElementMethod(this.render, elementIndex, methodName, args);
}
// implementation of EventDispatcher#dispatchEvent