feat(compiler): added support for host actions
This commit is contained in:
18
modules/angular2/src/render/api.js
vendored
18
modules/angular2/src/render/api.js
vendored
@ -117,16 +117,18 @@ export class DirectiveMetadata {
|
||||
hostListeners:Map<string, string>;
|
||||
hostProperties:Map<string, string>;
|
||||
hostAttributes:Map<string, string>;
|
||||
hostActions:Map<string, string>;
|
||||
properties:Map<string, string>;
|
||||
readAttributes:List<string>;
|
||||
type:number;
|
||||
constructor({id, selector, compileChildren, hostListeners, hostProperties, hostAttributes, properties, readAttributes, type}) {
|
||||
constructor({id, selector, compileChildren, hostListeners, hostProperties, hostAttributes, hostActions, properties, readAttributes, type}) {
|
||||
this.id = id;
|
||||
this.selector = selector;
|
||||
this.compileChildren = isPresent(compileChildren) ? compileChildren : true;
|
||||
this.hostListeners = hostListeners;
|
||||
this.hostProperties = hostProperties;
|
||||
this.hostAttributes = hostAttributes;
|
||||
this.hostActions = hostActions;
|
||||
this.properties = properties;
|
||||
this.readAttributes = readAttributes;
|
||||
this.type = type;
|
||||
@ -228,7 +230,7 @@ export class Renderer {
|
||||
/**
|
||||
* Hydrates a view after it has been attached. Hydration/dehydration is used for reusing views inside of the view pool.
|
||||
*/
|
||||
hydrateView(hviewRef:RenderViewRef) {
|
||||
hydrateView(viewRef:RenderViewRef) {
|
||||
}
|
||||
|
||||
/**
|
||||
@ -238,14 +240,22 @@ export class Renderer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a porperty on an element.
|
||||
* Sets a property on an element.
|
||||
* Note: This will fail if the property was not mentioned previously as a host property
|
||||
* in the ProtoView
|
||||
*/
|
||||
setElementProperty(viewRef:RenderViewRef, elementIndex:number, propertyName:string, propertyValue:any):void {
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Calls an action.
|
||||
* Note: This will fail if the action was not mentioned previously as a host action
|
||||
* in the ProtoView
|
||||
*/
|
||||
callAction(viewRef:RenderViewRef, elementIndex:number, actionExpression:string, actionArgs:any):void {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of a text node.
|
||||
*/
|
||||
setText(viewRef:RenderViewRef, textNodeIndex:number, text:string):void {
|
||||
|
@ -73,6 +73,11 @@ export class DirectiveParser extends CompileStep {
|
||||
this._bindDirectiveEvent(eventName, action, current, directiveBinderBuilder);
|
||||
});
|
||||
}
|
||||
if (isPresent(directive.hostActions)) {
|
||||
MapWrapper.forEach(directive.hostActions, (action, actionName) => {
|
||||
this._bindHostAction(actionName, action, current, directiveBinderBuilder);
|
||||
});
|
||||
}
|
||||
if (isPresent(directive.hostProperties)) {
|
||||
MapWrapper.forEach(directive.hostProperties, (hostPropertyName, directivePropertyName) => {
|
||||
this._bindHostProperty(hostPropertyName, directivePropertyName, current, directiveBinderBuilder);
|
||||
@ -136,7 +141,11 @@ export class DirectiveParser extends CompileStep {
|
||||
} else {
|
||||
directiveBinderBuilder.bindEvent(eventName, ast);
|
||||
}
|
||||
}
|
||||
|
||||
_bindHostAction(actionName, actionExpression, compileElement, directiveBinderBuilder) {
|
||||
var ast = this._parser.parseAction(actionExpression, compileElement.elementDescription);
|
||||
directiveBinderBuilder.bindHostAction(actionName, actionExpression, ast);
|
||||
}
|
||||
|
||||
_bindHostProperty(hostPropertyName, directivePropertyName, compileElement, directiveBinderBuilder) {
|
||||
|
2
modules/angular2/src/render/dom/convert.js
vendored
2
modules/angular2/src/render/dom/convert.js
vendored
@ -14,6 +14,7 @@ export function directiveMetadataToMap(meta: DirectiveMetadata): Map {
|
||||
['hostListeners', _cloneIfPresent(meta.hostListeners)],
|
||||
['hostProperties', _cloneIfPresent(meta.hostProperties)],
|
||||
['hostAttributes', _cloneIfPresent(meta.hostAttributes)],
|
||||
['hostActions', _cloneIfPresent(meta.hostActions)],
|
||||
['properties', _cloneIfPresent(meta.properties)],
|
||||
['readAttributes', _cloneIfPresent(meta.readAttributes)],
|
||||
['type', meta.type],
|
||||
@ -33,6 +34,7 @@ export function directiveMetadataFromMap(map: Map): DirectiveMetadata {
|
||||
compileChildren: MapWrapper.get(map, 'compileChildren'),
|
||||
hostListeners: _cloneIfPresent(MapWrapper.get(map, 'hostListeners')),
|
||||
hostProperties: _cloneIfPresent(MapWrapper.get(map, 'hostProperties')),
|
||||
hostActions: _cloneIfPresent(MapWrapper.get(map, 'hostActions')),
|
||||
hostAttributes: _cloneIfPresent(MapWrapper.get(map, 'hostAttributes')),
|
||||
properties: _cloneIfPresent(MapWrapper.get(map, 'properties')),
|
||||
readAttributes: _cloneIfPresent(MapWrapper.get(map, 'readAttributes')),
|
||||
|
@ -192,6 +192,11 @@ export class DomRenderer extends Renderer {
|
||||
view.setElementProperty(elementIndex, propertyName, propertyValue);
|
||||
}
|
||||
|
||||
callAction(viewRef:RenderViewRef, elementIndex:number, actionExpression:string, actionArgs:any):void {
|
||||
var view = resolveInternalDomView(viewRef);
|
||||
view.callAction(elementIndex, actionExpression, actionArgs);
|
||||
}
|
||||
|
||||
setText(viewRef:RenderViewRef, textNodeIndex:number, text:string):void {
|
||||
var view = resolveInternalDomView(viewRef);
|
||||
DOM.setText(view.boundTextNodes[textNodeIndex], text);
|
||||
|
2
modules/angular2/src/render/dom/util.js
vendored
2
modules/angular2/src/render/dom/util.js
vendored
@ -18,4 +18,4 @@ export function dashCaseToCamelCase(input:string) {
|
||||
return StringWrapper.replaceAllMapped(input, DASH_CASE_REGEXP, (m) => {
|
||||
return m[1].toUpperCase();
|
||||
});
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ export class ElementBinder {
|
||||
parentIndex:number;
|
||||
distanceToParent:number;
|
||||
propertySetters: Map<string, SetterFn>;
|
||||
hostActions: Map<string, AST>;
|
||||
|
||||
constructor({
|
||||
textNodeIndices,
|
||||
@ -23,6 +24,7 @@ export class ElementBinder {
|
||||
eventLocals,
|
||||
localEvents,
|
||||
globalEvents,
|
||||
hostActions,
|
||||
parentIndex,
|
||||
distanceToParent,
|
||||
propertySetters
|
||||
@ -34,6 +36,7 @@ export class ElementBinder {
|
||||
this.eventLocals = eventLocals;
|
||||
this.localEvents = localEvents;
|
||||
this.globalEvents = globalEvents;
|
||||
this.hostActions = hostActions;
|
||||
this.parentIndex = parentIndex;
|
||||
this.distanceToParent = distanceToParent;
|
||||
this.propertySetters = propertySetters;
|
||||
@ -51,3 +54,15 @@ export class Event {
|
||||
this.fullName = fullName;
|
||||
}
|
||||
}
|
||||
|
||||
export class HostAction {
|
||||
actionName: string;
|
||||
actionExpression: string;
|
||||
expression: AST;
|
||||
|
||||
constructor(actionName: string, actionExpression: string, expression: AST) {
|
||||
this.actionName = actionName;
|
||||
this.actionExpression = actionExpression;
|
||||
this.expression = expression;
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import {
|
||||
} from 'angular2/change_detection';
|
||||
|
||||
import {DomProtoView, DomProtoViewRef, resolveInternalDomProtoView} from './proto_view';
|
||||
import {ElementBinder, Event} from './element_binder';
|
||||
import {ElementBinder, Event, HostAction} from './element_binder';
|
||||
import {setterFactory} from './property_setter_factory';
|
||||
|
||||
import * as api from '../../api';
|
||||
@ -48,6 +48,7 @@ export class ProtoViewBuilder {
|
||||
var apiElementBinders = [];
|
||||
ListWrapper.forEach(this.elements, (ebb) => {
|
||||
var propertySetters = MapWrapper.create();
|
||||
var hostActions = MapWrapper.create();
|
||||
|
||||
var apiDirectiveBinders = ListWrapper.map(ebb.directives, (dbb) => {
|
||||
ebb.eventBuilder.merge(dbb.eventBuilder);
|
||||
@ -56,6 +57,10 @@ export class ProtoViewBuilder {
|
||||
MapWrapper.set(propertySetters, hostPropertyName, setterFactory(hostPropertyName));
|
||||
});
|
||||
|
||||
ListWrapper.forEach(dbb.hostActions, (hostAction) => {
|
||||
MapWrapper.set(hostActions, hostAction.actionExpression, hostAction.expression);
|
||||
});
|
||||
|
||||
return new api.DirectiveBinder({
|
||||
directiveIndex: dbb.directiveIndex,
|
||||
propertyBindings: dbb.propertyBindings,
|
||||
@ -90,6 +95,7 @@ export class ProtoViewBuilder {
|
||||
eventLocals: new LiteralArray(ebb.eventBuilder.buildEventLocals()),
|
||||
localEvents: ebb.eventBuilder.buildLocalEvents(),
|
||||
globalEvents: ebb.eventBuilder.buildGlobalEvents(),
|
||||
hostActions: hostActions,
|
||||
propertySetters: propertySetters
|
||||
}));
|
||||
});
|
||||
@ -213,6 +219,7 @@ export class DirectiveBuilder {
|
||||
directiveIndex:number;
|
||||
propertyBindings: Map<string, ASTWithSource>;
|
||||
hostPropertyBindings: Map<string, ASTWithSource>;
|
||||
hostActions: List<HostAction>;
|
||||
eventBindings: List<api.EventBinding>;
|
||||
eventBuilder: EventBuilder;
|
||||
|
||||
@ -220,6 +227,7 @@ export class DirectiveBuilder {
|
||||
this.directiveIndex = directiveIndex;
|
||||
this.propertyBindings = MapWrapper.create();
|
||||
this.hostPropertyBindings = MapWrapper.create();
|
||||
this.hostActions = ListWrapper.create();
|
||||
this.eventBindings = ListWrapper.create();
|
||||
this.eventBuilder = new EventBuilder();
|
||||
}
|
||||
@ -232,6 +240,10 @@ export class DirectiveBuilder {
|
||||
MapWrapper.set(this.hostPropertyBindings, name, expression);
|
||||
}
|
||||
|
||||
bindHostAction(actionName:string, actionExpression:string, expression:ASTWithSource) {
|
||||
ListWrapper.push(this.hostActions, new HostAction(actionName, actionExpression, expression));
|
||||
}
|
||||
|
||||
bindEvent(name, expression, target = null) {
|
||||
ListWrapper.push(this.eventBindings, this.eventBuilder.add(name, expression, target));
|
||||
}
|
||||
|
13
modules/angular2/src/render/dom/view/view.js
vendored
13
modules/angular2/src/render/dom/view/view.js
vendored
@ -1,5 +1,6 @@
|
||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||
import {ListWrapper, MapWrapper, Map, StringMapWrapper, List} from 'angular2/src/facade/collection';
|
||||
import {Locals} from 'angular2/change_detection';
|
||||
import {int, isPresent, isBlank, BaseException} from 'angular2/src/facade/lang';
|
||||
|
||||
import {DomViewContainer} from './view_container';
|
||||
@ -80,6 +81,18 @@ export class DomView {
|
||||
setter(this.boundElements[elementIndex], value);
|
||||
}
|
||||
|
||||
callAction(elementIndex:number, actionExpression:string, actionArgs:any) {
|
||||
var binder = this.proto.elementBinders[elementIndex];
|
||||
var hostAction = MapWrapper.get(binder.hostActions, actionExpression);
|
||||
hostAction.eval(this.boundElements[elementIndex], this._localsWithAction(actionArgs));
|
||||
}
|
||||
|
||||
_localsWithAction(action:Object):Locals {
|
||||
var map = MapWrapper.create();
|
||||
MapWrapper.set(map, '$action', action);
|
||||
return new Locals(null, map);
|
||||
}
|
||||
|
||||
setText(textIndex:number, value:string) {
|
||||
DOM.setText(this.boundTextNodes[textIndex], value);
|
||||
}
|
||||
|
Reference in New Issue
Block a user