2015-03-06 15:44:59 +01:00
|
|
|
import {ListWrapper, MapWrapper, Map, StringMapWrapper, List} from 'angular2/src/facade/collection';
|
2015-03-11 21:11:39 -07:00
|
|
|
import {AST, Locals, ChangeDispatcher, ProtoChangeDetector, ChangeDetector,
|
2015-04-21 11:47:53 -07:00
|
|
|
ChangeRecord, BindingRecord, DirectiveRecord, DirectiveIndex, ChangeDetectorRef} from 'angular2/change_detection';
|
2014-11-13 15:15:55 -08:00
|
|
|
|
2015-04-02 14:40:49 -07:00
|
|
|
import {ProtoElementInjector, ElementInjector, PreBuiltObjects, DirectiveBinding} from './element_injector';
|
2014-11-11 17:33:47 -08:00
|
|
|
import {ElementBinder} from './element_binder';
|
2015-02-05 13:08:05 -08:00
|
|
|
import {SetterFn} from 'angular2/src/reflection/types';
|
2015-03-11 16:45:36 +01:00
|
|
|
import {IMPLEMENTS, int, isPresent, isBlank, BaseException} from 'angular2/src/facade/lang';
|
2015-02-12 11:54:22 +01:00
|
|
|
import {ViewContainer} from './view_container';
|
2015-04-07 17:24:09 -07:00
|
|
|
import * as renderApi from 'angular2/src/render/api';
|
2015-04-16 15:38:28 -07:00
|
|
|
import * as vfModule from './view_factory';
|
|
|
|
import * as vhModule from './view_hydrator';
|
2014-09-28 16:29:11 -07:00
|
|
|
|
2014-11-21 15:13:01 -08:00
|
|
|
/**
|
2014-10-10 20:44:55 -07:00
|
|
|
* Const of making objects: http://jsperf.com/instantiate-size-of-object
|
2015-03-31 22:47:11 +00:00
|
|
|
*
|
2014-10-10 20:44:55 -07:00
|
|
|
*/
|
2014-12-04 13:16:38 +01:00
|
|
|
@IMPLEMENTS(ChangeDispatcher)
|
2015-04-07 20:54:20 -07:00
|
|
|
// TODO(tbosch): this is not supported in dart2js (no '.' is allowed)
|
|
|
|
// @IMPLEMENTS(renderApi.EventDispatcher)
|
2015-04-09 21:20:11 +02:00
|
|
|
export class AppView {
|
2015-04-07 20:54:20 -07:00
|
|
|
render:renderApi.ViewRef;
|
2014-09-28 16:29:11 -07:00
|
|
|
/// This list matches the _nodes list. It is sparse, since only Elements have ElementInjector
|
2014-11-21 21:19:23 -08:00
|
|
|
rootElementInjectors:List<ElementInjector>;
|
|
|
|
elementInjectors:List<ElementInjector>;
|
2015-01-14 13:51:16 -08:00
|
|
|
changeDetector:ChangeDetector;
|
2015-04-09 21:20:11 +02:00
|
|
|
componentChildViews: List<AppView>;
|
2015-04-20 11:34:53 -07:00
|
|
|
/// Host views that were added by an imperative view.
|
|
|
|
/// This is a dynamically growing / shrinking array.
|
|
|
|
imperativeHostViews: List<AppView>;
|
2015-02-12 11:54:22 +01:00
|
|
|
viewContainers: List<ViewContainer>;
|
2014-12-01 18:41:55 -08:00
|
|
|
preBuiltObjects: List<PreBuiltObjects>;
|
2015-04-09 21:20:11 +02:00
|
|
|
proto: AppProtoView;
|
2015-04-15 21:51:30 -07:00
|
|
|
renderer: renderApi.Renderer;
|
2015-04-16 15:38:28 -07:00
|
|
|
viewFactory: vfModule.ViewFactory;
|
|
|
|
viewHydrator: vhModule.AppViewHydrator;
|
2015-04-06 13:19:30 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The context against which data-binding expressions in this view are evaluated against.
|
|
|
|
* This is always a component instance.
|
|
|
|
*/
|
2015-04-09 21:20:11 +02:00
|
|
|
|
2014-12-29 12:12:11 -08:00
|
|
|
context: any;
|
2015-04-06 13:19:30 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Variables, local to this view, that can be used in binding expressions (in addition to the
|
|
|
|
* context). This is used for thing like `<video #player>` or
|
|
|
|
* `<li template="for #item of items">`, where "player" and "item" are locals, respectively.
|
|
|
|
*/
|
2015-03-11 21:11:39 -07:00
|
|
|
locals:Locals;
|
2015-01-02 14:23:59 -08:00
|
|
|
|
2015-04-20 11:34:53 -07:00
|
|
|
constructor(renderer:renderApi.Renderer, viewFactory:vfModule.ViewFactory, proto:AppProtoView, protoLocals:Map) {
|
2015-04-07 20:54:20 -07:00
|
|
|
this.render = null;
|
2014-12-01 18:41:55 -08:00
|
|
|
this.proto = proto;
|
2015-03-11 21:43:22 -07:00
|
|
|
this.changeDetector = null;
|
2014-12-09 10:31:19 -08:00
|
|
|
this.elementInjectors = null;
|
|
|
|
this.rootElementInjectors = null;
|
2014-11-21 15:13:01 -08:00
|
|
|
this.componentChildViews = null;
|
2015-04-16 15:38:28 -07:00
|
|
|
this.viewContainers = ListWrapper.createFixedSize(this.proto.elementBinders.length);
|
2014-12-01 18:41:55 -08:00
|
|
|
this.preBuiltObjects = null;
|
|
|
|
this.context = null;
|
2015-03-11 21:11:39 -07:00
|
|
|
this.locals = new Locals(null, MapWrapper.clone(protoLocals)); //TODO optimize this
|
2015-04-15 21:51:30 -07:00
|
|
|
this.renderer = renderer;
|
2015-04-16 15:38:28 -07:00
|
|
|
this.viewFactory = viewFactory;
|
2015-04-20 11:34:53 -07:00
|
|
|
this.viewHydrator = null;
|
|
|
|
this.imperativeHostViews = [];
|
2014-12-01 18:41:55 -08:00
|
|
|
}
|
|
|
|
|
2015-04-07 20:54:20 -07:00
|
|
|
init(changeDetector:ChangeDetector, elementInjectors:List, rootElementInjectors:List,
|
2015-04-16 15:38:28 -07:00
|
|
|
preBuiltObjects:List, componentChildViews:List) {
|
2015-03-11 21:43:22 -07:00
|
|
|
this.changeDetector = changeDetector;
|
2014-12-09 10:31:19 -08:00
|
|
|
this.elementInjectors = elementInjectors;
|
|
|
|
this.rootElementInjectors = rootElementInjectors;
|
|
|
|
this.preBuiltObjects = preBuiltObjects;
|
|
|
|
this.componentChildViews = componentChildViews;
|
2014-12-01 18:41:55 -08:00
|
|
|
}
|
|
|
|
|
2015-04-19 14:47:02 -07:00
|
|
|
getOrCreateViewContainer(boundElementIndex:number):ViewContainer {
|
2015-04-16 15:38:28 -07:00
|
|
|
var viewContainer = this.viewContainers[boundElementIndex];
|
|
|
|
if (isBlank(viewContainer)) {
|
|
|
|
viewContainer = new ViewContainer(this, this.proto.elementBinders[boundElementIndex].nestedProtoView, this.elementInjectors[boundElementIndex]);
|
|
|
|
this.viewContainers[boundElementIndex] = viewContainer;
|
|
|
|
}
|
|
|
|
return viewContainer;
|
|
|
|
}
|
|
|
|
|
2015-04-19 14:47:02 -07:00
|
|
|
setLocal(contextName: string, value):void {
|
2014-12-01 18:41:55 -08:00
|
|
|
if (!this.hydrated()) throw new BaseException('Cannot set locals on dehydrated view.');
|
|
|
|
if (!MapWrapper.contains(this.proto.variableBindings, contextName)) {
|
2015-01-28 00:42:08 +01:00
|
|
|
return;
|
2014-12-01 18:41:55 -08:00
|
|
|
}
|
|
|
|
var templateName = MapWrapper.get(this.proto.variableBindings, contextName);
|
2015-03-11 21:11:39 -07:00
|
|
|
this.locals.set(templateName, value);
|
2014-12-01 18:41:55 -08:00
|
|
|
}
|
|
|
|
|
2015-04-19 14:47:02 -07:00
|
|
|
hydrated():boolean {
|
2014-12-01 18:41:55 -08:00
|
|
|
return isPresent(this.context);
|
|
|
|
}
|
|
|
|
|
2015-03-10 10:03:26 +01:00
|
|
|
/**
|
|
|
|
* Triggers the event handlers for the element and the directives.
|
|
|
|
*
|
|
|
|
* This method is intended to be called from directive EventEmitters.
|
|
|
|
*
|
|
|
|
* @param {string} eventName
|
|
|
|
* @param {*} eventObj
|
|
|
|
* @param {int} binderIndex
|
|
|
|
*/
|
2015-04-19 14:47:02 -07:00
|
|
|
triggerEventHandlers(eventName: string, eventObj, binderIndex: int): void {
|
2015-04-07 20:54:20 -07:00
|
|
|
var locals = MapWrapper.create();
|
|
|
|
MapWrapper.set(locals, '$event', eventObj);
|
|
|
|
this.dispatchEvent(binderIndex, eventName, locals);
|
2015-03-10 10:03:26 +01:00
|
|
|
}
|
|
|
|
|
2015-03-31 09:07:01 -07:00
|
|
|
// dispatch to element injector or text nodes based on context
|
2015-04-19 14:47:02 -07:00
|
|
|
notifyOnBinding(b:BindingRecord, currentValue:any): void {
|
2015-04-09 07:57:33 -07:00
|
|
|
if (b.isElement()) {
|
2015-04-15 21:51:30 -07:00
|
|
|
this.renderer.setElementProperty(
|
2015-04-09 07:57:33 -07:00
|
|
|
this.render, b.elementIndex, b.propertyName, currentValue
|
2015-04-07 20:54:20 -07:00
|
|
|
);
|
2014-09-28 16:29:11 -07:00
|
|
|
} else {
|
2014-10-10 20:44:55 -07:00
|
|
|
// we know it refers to _textNodes.
|
2015-04-15 21:51:30 -07:00
|
|
|
this.renderer.setText(this.render, b.elementIndex, currentValue);
|
2015-04-07 20:54:20 -07:00
|
|
|
}
|
|
|
|
}
|
2015-04-09 21:20:11 +02:00
|
|
|
|
2015-04-21 11:47:53 -07:00
|
|
|
getDirectiveFor(directive:DirectiveIndex) {
|
2015-04-14 08:54:09 -07:00
|
|
|
var elementInjector = this.elementInjectors[directive.elementIndex];
|
2015-04-09 07:57:33 -07:00
|
|
|
return elementInjector.getDirectiveAtIndex(directive.directiveIndex);
|
|
|
|
}
|
2015-04-07 20:54:20 -07:00
|
|
|
|
2015-04-21 11:47:53 -07:00
|
|
|
getDetectorFor(directive:DirectiveIndex) {
|
2015-04-14 08:54:09 -07:00
|
|
|
var elementInjector = this.elementInjectors[directive.elementIndex];
|
|
|
|
return elementInjector.getChangeDetector();
|
|
|
|
}
|
|
|
|
|
2015-04-07 20:54:20 -07:00
|
|
|
// implementation of EventDispatcher#dispatchEvent
|
2015-04-16 18:03:15 +02:00
|
|
|
// returns false if preventDefault must be applied to the DOM event
|
|
|
|
dispatchEvent(elementIndex:number, eventName:string, locals:Map<string, any>): boolean {
|
2015-04-07 20:54:20 -07:00
|
|
|
// Most of the time the event will be fired only when the view is in the live document.
|
|
|
|
// However, in a rare circumstance the view might get dehydrated, in between the event
|
|
|
|
// queuing up and firing.
|
2015-04-16 18:03:15 +02:00
|
|
|
var allowDefaultBehavior = true;
|
2015-04-07 20:54:20 -07:00
|
|
|
if (this.hydrated()) {
|
|
|
|
var elBinder = this.proto.elementBinders[elementIndex];
|
2015-04-16 18:03:15 +02:00
|
|
|
if (isBlank(elBinder.hostListeners)) return allowDefaultBehavior;
|
2015-04-09 21:20:11 +02:00
|
|
|
var eventMap = elBinder.hostListeners[eventName];
|
2015-04-16 18:03:15 +02:00
|
|
|
if (isBlank(eventMap)) return allowDefaultBehavior;
|
2015-04-07 20:54:20 -07:00
|
|
|
MapWrapper.forEach(eventMap, (expr, directiveIndex) => {
|
|
|
|
var context;
|
|
|
|
if (directiveIndex === -1) {
|
|
|
|
context = this.context;
|
|
|
|
} else {
|
|
|
|
context = this.elementInjectors[elementIndex].getDirectiveAtIndex(directiveIndex);
|
|
|
|
}
|
2015-04-16 18:03:15 +02:00
|
|
|
var result = expr.eval(context, new Locals(this.locals, locals));
|
|
|
|
if (isPresent(result)) {
|
2015-04-20 11:34:53 -07:00
|
|
|
allowDefaultBehavior = allowDefaultBehavior && result;
|
2015-04-16 18:03:15 +02:00
|
|
|
}
|
2015-04-07 20:54:20 -07:00
|
|
|
});
|
2014-12-02 17:09:46 -08:00
|
|
|
}
|
2015-04-16 18:03:15 +02:00
|
|
|
return allowDefaultBehavior;
|
2014-12-02 17:09:46 -08:00
|
|
|
}
|
2014-09-28 16:29:11 -07:00
|
|
|
}
|
|
|
|
|
2015-03-17 19:22:13 +00:00
|
|
|
/**
|
2015-03-31 22:47:11 +00:00
|
|
|
*
|
2015-03-17 19:22:13 +00:00
|
|
|
*/
|
2015-04-09 21:20:11 +02:00
|
|
|
export class AppProtoView {
|
2014-11-21 21:19:23 -08:00
|
|
|
elementBinders:List<ElementBinder>;
|
2015-01-14 13:51:16 -08:00
|
|
|
protoChangeDetector:ProtoChangeDetector;
|
2014-11-21 21:19:23 -08:00
|
|
|
variableBindings: Map;
|
2015-03-11 21:11:39 -07:00
|
|
|
protoLocals:Map;
|
2014-11-21 21:19:23 -08:00
|
|
|
textNodesWithBindingCount:int;
|
2015-04-09 07:57:33 -07:00
|
|
|
bindings:List;
|
2015-04-09 21:20:11 +02:00
|
|
|
parentProtoView:AppProtoView;
|
2015-03-11 21:11:39 -07:00
|
|
|
_variableBindings:List;
|
2015-02-24 16:05:45 +01:00
|
|
|
|
2015-04-09 07:57:33 -07:00
|
|
|
_directiveRecordsMap:Map;
|
|
|
|
_directiveRecords:List;
|
2015-04-07 17:24:09 -07:00
|
|
|
render:renderApi.ProtoViewRef;
|
2015-03-26 14:36:25 -07:00
|
|
|
|
2014-09-28 20:02:32 -07:00
|
|
|
constructor(
|
2015-04-07 17:24:09 -07:00
|
|
|
render:renderApi.ProtoViewRef,
|
2015-04-07 20:54:20 -07:00
|
|
|
protoChangeDetector:ProtoChangeDetector) {
|
2015-04-07 17:24:09 -07:00
|
|
|
this.render = render;
|
2014-11-11 17:33:47 -08:00
|
|
|
this.elementBinders = [];
|
2014-11-18 16:38:36 -08:00
|
|
|
this.variableBindings = MapWrapper.create();
|
2015-03-11 21:11:39 -07:00
|
|
|
this.protoLocals = MapWrapper.create();
|
2015-01-14 13:51:16 -08:00
|
|
|
this.protoChangeDetector = protoChangeDetector;
|
2015-04-07 20:54:20 -07:00
|
|
|
this.parentProtoView = null;
|
2014-11-11 17:33:47 -08:00
|
|
|
this.textNodesWithBindingCount = 0;
|
2015-04-09 07:57:33 -07:00
|
|
|
this.bindings = [];
|
|
|
|
this._directiveRecordsMap = MapWrapper.create();
|
2015-03-11 21:11:39 -07:00
|
|
|
this._variableBindings = null;
|
2015-04-09 07:57:33 -07:00
|
|
|
this._directiveRecords = null;
|
2014-09-28 20:02:32 -07:00
|
|
|
}
|
|
|
|
|
2015-03-27 11:02:55 -07:00
|
|
|
//TODO: Tobias or Victor. Moving it into the constructor.
|
2015-04-09 21:20:11 +02:00
|
|
|
// this work should be done the constructor of AppProtoView once we separate
|
|
|
|
// AppProtoView and ProtoViewBuilder
|
2015-04-19 14:47:02 -07:00
|
|
|
getVariableBindings(): List {
|
2015-03-11 21:11:39 -07:00
|
|
|
if (isPresent(this._variableBindings)) {
|
|
|
|
return this._variableBindings;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._variableBindings = isPresent(this.parentProtoView) ?
|
2015-04-07 20:54:20 -07:00
|
|
|
ListWrapper.clone(this.parentProtoView.getVariableBindings()) : [];
|
2015-03-11 21:11:39 -07:00
|
|
|
|
|
|
|
MapWrapper.forEach(this.protoLocals, (v, local) => {
|
|
|
|
ListWrapper.push(this._variableBindings, local);
|
|
|
|
});
|
|
|
|
|
|
|
|
return this._variableBindings;
|
|
|
|
}
|
|
|
|
|
2015-03-27 11:02:55 -07:00
|
|
|
//TODO: Tobias or Victor. Moving it into the constructor.
|
2015-03-26 14:36:25 -07:00
|
|
|
// this work should be done the constructor of ProtoView once we separate
|
2015-04-09 21:20:11 +02:00
|
|
|
// AppProtoView and ProtoViewBuilder
|
2015-04-19 14:47:02 -07:00
|
|
|
getdirectiveRecords(): List {
|
2015-04-09 07:57:33 -07:00
|
|
|
if (isPresent(this._directiveRecords)) {
|
|
|
|
return this._directiveRecords;
|
2015-03-26 14:36:25 -07:00
|
|
|
}
|
|
|
|
|
2015-04-09 07:57:33 -07:00
|
|
|
this._directiveRecords = [];
|
2015-03-26 14:36:25 -07:00
|
|
|
|
|
|
|
for (var injectorIndex = 0; injectorIndex < this.elementBinders.length; ++injectorIndex) {
|
|
|
|
var pei = this.elementBinders[injectorIndex].protoElementInjector;
|
|
|
|
if (isPresent(pei)) {
|
|
|
|
for (var directiveIndex = 0; directiveIndex < pei.numberOfDirectives; ++directiveIndex) {
|
2015-04-09 07:57:33 -07:00
|
|
|
ListWrapper.push(this._directiveRecords, this._getDirectiveRecord(injectorIndex, directiveIndex));
|
2015-03-26 14:36:25 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-09 07:57:33 -07:00
|
|
|
return this._directiveRecords;
|
2015-03-26 14:36:25 -07:00
|
|
|
}
|
|
|
|
|
2015-04-19 14:47:02 -07:00
|
|
|
bindVariable(contextName:string, templateName:string): void {
|
2014-11-18 16:38:36 -08:00
|
|
|
MapWrapper.set(this.variableBindings, contextName, templateName);
|
2015-03-11 21:11:39 -07:00
|
|
|
MapWrapper.set(this.protoLocals, templateName, null);
|
2014-11-18 16:38:36 -08:00
|
|
|
}
|
|
|
|
|
2015-03-16 11:31:58 -07:00
|
|
|
bindElement(parent:ElementBinder, distanceToParent:int, protoElementInjector:ProtoElementInjector,
|
2015-04-02 14:40:49 -07:00
|
|
|
componentDirective:DirectiveBinding = null, viewportDirective:DirectiveBinding = null):ElementBinder {
|
2015-04-02 09:52:00 -07:00
|
|
|
var elBinder = new ElementBinder(this.elementBinders.length, parent, distanceToParent,
|
2015-03-16 11:31:58 -07:00
|
|
|
protoElementInjector, componentDirective, viewportDirective);
|
2014-11-11 17:33:47 -08:00
|
|
|
ListWrapper.push(this.elementBinders, elBinder);
|
|
|
|
return elBinder;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds a text node binding for the last created ElementBinder via bindElement
|
|
|
|
*/
|
2015-04-19 14:47:02 -07:00
|
|
|
bindTextNode(expression:AST):void {
|
2015-04-09 07:57:33 -07:00
|
|
|
var textNodeIndex = this.textNodesWithBindingCount++;
|
|
|
|
var b = BindingRecord.createForTextNode(expression, textNodeIndex);
|
|
|
|
ListWrapper.push(this.bindings, b);
|
2014-11-11 17:33:47 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds an element property binding for the last created ElementBinder via bindElement
|
|
|
|
*/
|
2015-04-19 14:47:02 -07:00
|
|
|
bindElementProperty(expression:AST, setterName:string):void {
|
2015-04-09 07:57:33 -07:00
|
|
|
var elementIndex = this.elementBinders.length-1;
|
|
|
|
var b = BindingRecord.createForElement(expression, elementIndex, setterName);
|
|
|
|
ListWrapper.push(this.bindings, b);
|
2014-11-11 17:33:47 -08:00
|
|
|
}
|
|
|
|
|
2015-04-21 11:47:53 -07:00
|
|
|
/**
|
|
|
|
* Adds an host property binding for the last created ElementBinder via bindElement
|
|
|
|
*/
|
|
|
|
bindHostElementProperty(expression:AST, setterName:string, directiveIndex:DirectiveIndex):void {
|
|
|
|
var b = BindingRecord.createForHostProperty(directiveIndex, expression, setterName);
|
|
|
|
ListWrapper.push(this.bindings, b);
|
|
|
|
}
|
|
|
|
|
2014-11-19 14:54:07 -08:00
|
|
|
/**
|
2015-03-06 15:44:59 +01:00
|
|
|
* Adds an event binding for the last created ElementBinder via bindElement.
|
|
|
|
*
|
|
|
|
* If the directive index is a positive integer, the event is evaluated in the context of
|
|
|
|
* the given directive.
|
|
|
|
*
|
|
|
|
* If the directive index is -1, the event is evaluated in the context of the enclosing view.
|
|
|
|
*
|
|
|
|
* @param {string} eventName
|
|
|
|
* @param {AST} expression
|
|
|
|
* @param {int} directiveIndex The directive index in the binder or -1 when the event is not bound
|
|
|
|
* to a directive
|
2014-11-19 14:54:07 -08:00
|
|
|
*/
|
2015-04-19 14:47:02 -07:00
|
|
|
bindEvent(eventBindings: List<renderApi.EventBinding>, directiveIndex: int = -1): void {
|
2015-03-06 15:44:59 +01:00
|
|
|
var elBinder = this.elementBinders[this.elementBinders.length - 1];
|
2015-04-09 21:20:11 +02:00
|
|
|
var events = elBinder.hostListeners;
|
2015-03-06 15:44:59 +01:00
|
|
|
if (isBlank(events)) {
|
|
|
|
events = StringMapWrapper.create();
|
2015-04-09 21:20:11 +02:00
|
|
|
elBinder.hostListeners = events;
|
2015-03-06 15:44:59 +01:00
|
|
|
}
|
2015-04-02 15:56:58 +02:00
|
|
|
for (var i = 0; i < eventBindings.length; i++) {
|
|
|
|
var eventBinding = eventBindings[i];
|
|
|
|
var eventName = eventBinding.fullName;
|
|
|
|
var event = StringMapWrapper.get(events, eventName);
|
|
|
|
if (isBlank(event)) {
|
|
|
|
event = MapWrapper.create();
|
|
|
|
StringMapWrapper.set(events, eventName, event);
|
|
|
|
}
|
|
|
|
MapWrapper.set(event, directiveIndex, eventBinding.source);
|
2014-11-19 14:54:07 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-11 17:33:47 -08:00
|
|
|
/**
|
|
|
|
* Adds a directive property binding for the last created ElementBinder via bindElement
|
|
|
|
*/
|
|
|
|
bindDirectiveProperty(
|
|
|
|
directiveIndex:number,
|
|
|
|
expression:AST,
|
|
|
|
setterName:string,
|
2015-04-19 14:47:02 -07:00
|
|
|
setter:SetterFn): void {
|
2014-12-02 17:09:46 -08:00
|
|
|
|
2015-03-26 14:36:25 -07:00
|
|
|
var elementIndex = this.elementBinders.length-1;
|
2015-04-09 07:57:33 -07:00
|
|
|
var directiveRecord = this._getDirectiveRecord(elementIndex, directiveIndex);
|
|
|
|
var b = BindingRecord.createForDirective(expression, setterName, setter, directiveRecord);
|
|
|
|
ListWrapper.push(this.bindings, b);
|
2014-10-27 11:47:13 -04:00
|
|
|
}
|
2015-04-02 09:52:00 -07:00
|
|
|
|
2015-04-19 14:47:02 -07:00
|
|
|
_getDirectiveRecord(elementInjectorIndex:number, directiveIndex:number): DirectiveRecord {
|
2015-03-26 14:36:25 -07:00
|
|
|
var id = elementInjectorIndex * 100 + directiveIndex;
|
|
|
|
var protoElementInjector = this.elementBinders[elementInjectorIndex].protoElementInjector;
|
2015-04-02 09:52:00 -07:00
|
|
|
|
2015-04-09 07:57:33 -07:00
|
|
|
if (!MapWrapper.contains(this._directiveRecordsMap, id)) {
|
2015-03-26 14:36:25 -07:00
|
|
|
var binding = protoElementInjector.getDirectiveBindingAtIndex(directiveIndex);
|
2015-04-14 08:54:09 -07:00
|
|
|
var changeDetection = binding.changeDetection;
|
|
|
|
|
2015-04-09 07:57:33 -07:00
|
|
|
MapWrapper.set(this._directiveRecordsMap, id,
|
2015-04-21 11:47:53 -07:00
|
|
|
new DirectiveRecord(new DirectiveIndex(elementInjectorIndex, directiveIndex),
|
2015-04-14 08:54:09 -07:00
|
|
|
binding.callOnAllChangesDone, binding.callOnChange, changeDetection));
|
2015-03-26 14:36:25 -07:00
|
|
|
}
|
2015-04-02 09:52:00 -07:00
|
|
|
|
2015-04-09 07:57:33 -07:00
|
|
|
return MapWrapper.get(this._directiveRecordsMap, id);
|
2015-02-06 13:19:47 -08:00
|
|
|
}
|
2015-04-09 21:20:11 +02:00
|
|
|
}
|