feat(compiler): support on-
and []
This commit is contained in:
@ -1,5 +1,6 @@
|
||||
import {ProtoElementInjector} from './element_injector';
|
||||
import {FIELD} from 'facade/lang';
|
||||
import {MapWrapper} from 'facade/collection';
|
||||
import {AnnotatedType} from './annotated_type';
|
||||
// Comment out as dartanalyzer does not look into @FIELD
|
||||
// import {List} from 'facade/collection';
|
||||
@ -11,12 +12,15 @@ export class ElementBinder {
|
||||
@FIELD('final templateDirective:AnnotatedType')
|
||||
@FIELD('final textNodeIndices:List<int>')
|
||||
@FIELD('hasElementPropertyBindings:bool')
|
||||
constructor(protoElementInjector: ProtoElementInjector, componentDirective:AnnotatedType, templateDirective:AnnotatedType) {
|
||||
constructor(
|
||||
protoElementInjector: ProtoElementInjector, componentDirective:AnnotatedType, templateDirective:AnnotatedType) {
|
||||
this.protoElementInjector = protoElementInjector;
|
||||
this.componentDirective = componentDirective;
|
||||
this.templateDirective = templateDirective;
|
||||
// updated later when events are bound
|
||||
this.events = null;
|
||||
// updated later when text nodes are bound
|
||||
this.textNodeIndices = [];
|
||||
this.textNodeIndices = null;
|
||||
// updated later when element properties are bound
|
||||
this.hasElementPropertyBindings = false;
|
||||
// updated later, so we are able to resolve cycles
|
||||
|
@ -20,6 +20,7 @@ export class CompileElement {
|
||||
this._classList = null;
|
||||
this.textNodeBindings = null;
|
||||
this.propertyBindings = null;
|
||||
this.eventBindings = null;
|
||||
this.variableBindings = null;
|
||||
this.decoratorDirectives = null;
|
||||
this.templateDirective = null;
|
||||
@ -84,6 +85,13 @@ export class CompileElement {
|
||||
MapWrapper.set(this.variableBindings, contextName, templateName);
|
||||
}
|
||||
|
||||
addEventBinding(eventName:string, expression:ASTWithSource) {
|
||||
if (isBlank(this.eventBindings)) {
|
||||
this.eventBindings = MapWrapper.create();
|
||||
}
|
||||
MapWrapper.set(this.eventBindings, eventName, expression);
|
||||
}
|
||||
|
||||
addDirective(directive:AnnotatedType) {
|
||||
var annotation = directive.annotation;
|
||||
if (annotation instanceof Decorator) {
|
||||
|
@ -33,6 +33,7 @@ import {CompileControl} from './compile_control';
|
||||
* - CompileElement#inheritedProtoElementInjector
|
||||
* - CompileElement#textNodeBindings
|
||||
* - CompileElement#propertyBindings
|
||||
* - CompileElement#eventBindings
|
||||
* - CompileElement#decoratorDirectives
|
||||
* - CompileElement#componentDirective
|
||||
* - CompileElement#templateDirective
|
||||
@ -60,6 +61,9 @@ export class ElementBinderBuilder extends CompileStep {
|
||||
if (isPresent(current.propertyBindings)) {
|
||||
this._bindElementProperties(protoView, current);
|
||||
}
|
||||
if (isPresent(current.eventBindings)) {
|
||||
this._bindEvents(protoView, current);
|
||||
}
|
||||
this._bindDirectiveProperties(this._collectDirectives(current), current);
|
||||
} else if (isPresent(parent)) {
|
||||
elementBinder = parent.inheritedElementBinder;
|
||||
@ -79,6 +83,12 @@ export class ElementBinderBuilder extends CompileStep {
|
||||
});
|
||||
}
|
||||
|
||||
_bindEvents(protoView, compileElement) {
|
||||
MapWrapper.forEach(compileElement.eventBindings, (expression, eventName) => {
|
||||
protoView.bindEvent(eventName, expression.ast);
|
||||
});
|
||||
}
|
||||
|
||||
_collectDirectives(compileElement) {
|
||||
var directives;
|
||||
if (isPresent(compileElement.decoratorDirectives)) {
|
||||
|
@ -19,6 +19,7 @@ const NG_BINDING_CLASS = 'ng-binding';
|
||||
* - CompileElement#textNodeBindings
|
||||
* - CompileElement#propertyBindings
|
||||
* - CompileElement#variableBindings
|
||||
* - CompileElement#eventBindings
|
||||
* - CompileElement#decoratorDirectives
|
||||
* - CompileElement#componentDirective
|
||||
* - CompileElement#templateDirective
|
||||
@ -29,6 +30,7 @@ export class ElementBindingMarker extends CompileStep {
|
||||
(isPresent(current.textNodeBindings) && MapWrapper.size(current.textNodeBindings)>0) ||
|
||||
(isPresent(current.propertyBindings) && MapWrapper.size(current.propertyBindings)>0) ||
|
||||
(isPresent(current.variableBindings) && MapWrapper.size(current.variableBindings)>0) ||
|
||||
(isPresent(current.eventBindings) && MapWrapper.size(current.eventBindings)>0) ||
|
||||
(isPresent(current.decoratorDirectives) && current.decoratorDirectives.length > 0) ||
|
||||
isPresent(current.templateDirective) ||
|
||||
isPresent(current.componentDirective);
|
||||
|
@ -12,13 +12,15 @@ import {CompileControl} from './compile_control';
|
||||
import {interpolationToExpression} from './text_interpolation_parser';
|
||||
|
||||
// TODO(tbosch): Cannot make this const/final right now because of the transpiler...
|
||||
var BIND_NAME_REGEXP = RegExpWrapper.create('^(?:(?:(bind)|(let))-(.+))|\\[([^\\]]+)\\]');
|
||||
var BIND_NAME_REGEXP = RegExpWrapper.create('^(?:(?:(bind)|(let)|(on))-(.+))|\\[([^\\]]+)\\]|\\(([^\\]]+)\\)');
|
||||
|
||||
/**
|
||||
* Parses the property bindings on a single element.
|
||||
*
|
||||
* Fills:
|
||||
* - CompileElement#propertyBindings
|
||||
* - CompileElement#eventBindings
|
||||
* - CompileElement#variableBindings
|
||||
*/
|
||||
export class PropertyBindingParser extends CompileStep {
|
||||
constructor(parser:Parser) {
|
||||
@ -32,7 +34,7 @@ export class PropertyBindingParser extends CompileStep {
|
||||
if (isPresent(bindParts)) {
|
||||
if (isPresent(bindParts[1])) {
|
||||
// match: bind-prop
|
||||
current.addPropertyBinding(bindParts[3], this._parser.parseBinding(attrValue));
|
||||
current.addPropertyBinding(bindParts[4], this._parser.parseBinding(attrValue));
|
||||
} else if (isPresent(bindParts[2])) {
|
||||
// match: let-prop
|
||||
// Note: We assume that the ViewSplitter already did its work, i.e. template directive should
|
||||
@ -40,10 +42,16 @@ export class PropertyBindingParser extends CompileStep {
|
||||
if (!(current.element instanceof TemplateElement)) {
|
||||
throw new BaseException('let-* is only allowed on <template> elements!');
|
||||
}
|
||||
current.addVariableBinding(bindParts[3], attrValue);
|
||||
} else if (isPresent(bindParts[4])) {
|
||||
current.addVariableBinding(bindParts[4], attrValue);
|
||||
} else if (isPresent(bindParts[3])) {
|
||||
// match: on-prop
|
||||
current.addEventBinding(bindParts[4], this._parser.parseAction(attrValue));
|
||||
} else if (isPresent(bindParts[5])) {
|
||||
// match: [prop]
|
||||
current.addPropertyBinding(bindParts[4], this._parser.parseBinding(attrValue));
|
||||
current.addPropertyBinding(bindParts[5], this._parser.parseBinding(attrValue));
|
||||
} else if (isPresent(bindParts[6])) {
|
||||
// match: (prop)
|
||||
current.addEventBinding(bindParts[6], this._parser.parseBinding(attrValue));
|
||||
}
|
||||
} else {
|
||||
var expression = interpolationToExpression(attrValue);
|
||||
|
@ -141,6 +141,9 @@ export class ProtoView {
|
||||
*/
|
||||
bindTextNode(indexInParent:int, expression:AST) {
|
||||
var elBinder = this.elementBinders[this.elementBinders.length-1];
|
||||
if (isBlank(elBinder.textNodeIndices)) {
|
||||
elBinder.textNodeIndices = ListWrapper.create();
|
||||
}
|
||||
ListWrapper.push(elBinder.textNodeIndices, indexInParent);
|
||||
this.protoWatchGroup.watch(expression, this.textNodesWithBindingCount++);
|
||||
}
|
||||
@ -162,6 +165,17 @@ export class ProtoView {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an event binding for the last created ElementBinder via bindElement
|
||||
*/
|
||||
bindEvent(eventName:string, expression:AST) {
|
||||
var elBinder = this.elementBinders[this.elementBinders.length-1];
|
||||
if (isBlank(elBinder.events)) {
|
||||
elBinder.events = MapWrapper.create();
|
||||
}
|
||||
MapWrapper.set(elBinder.events, eventName, expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a directive property binding for the last created ElementBinder via bindElement
|
||||
*/
|
||||
@ -228,9 +242,11 @@ export class ProtoView {
|
||||
}
|
||||
|
||||
static _collectTextNodes(allTextNodes, element, indices) {
|
||||
var childNodes = DOM.templateAwareRoot(element).childNodes;
|
||||
for (var i = 0; i < indices.length; ++i) {
|
||||
ListWrapper.push(allTextNodes, childNodes[indices[i]]);
|
||||
if (isPresent(indices)) {
|
||||
var childNodes = DOM.templateAwareRoot(element).childNodes;
|
||||
for (var i = 0; i < indices.length; ++i) {
|
||||
ListWrapper.push(allTextNodes, childNodes[indices[i]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user