diff --git a/lib/application_factory.dart b/lib/application_factory.dart index 8c46d4d4d..18b7ae2dd 100644 --- a/lib/application_factory.dart +++ b/lib/application_factory.dart @@ -51,6 +51,7 @@ import 'dart:html'; metaTargets: const [ Injectable, Decorator, + Template, Controller, Component, Formatter diff --git a/lib/core/annotation.dart b/lib/core/annotation.dart index 768def9aa..a5e7d3e57 100644 --- a/lib/core/annotation.dart +++ b/lib/core/annotation.dart @@ -17,6 +17,7 @@ export "package:angular/core/annotation_src.dart" show Component, Controller, Decorator, + Template, DirectiveAnnotation, NgAttr, diff --git a/lib/core/annotation_src.dart b/lib/core/annotation_src.dart index 643339ca9..67b41de76 100644 --- a/lib/core/annotation_src.dart +++ b/lib/core/annotation_src.dart @@ -6,19 +6,18 @@ RegExp _ATTR_NAME = new RegExp(r'\[([^\]]+)\]$'); const String SHADOW_DOM_INJECTOR_NAME = 'SHADOW_INJECTOR'; -skipShadow(Injector injector) - => injector.name == SHADOW_DOM_INJECTOR_NAME ? injector.parent : injector; +skipShadow(Injector injector) => + injector.name == SHADOW_DOM_INJECTOR_NAME ? injector.parent : injector; -localVisibility (Injector requesting, Injector defining) - => identical(skipShadow(requesting), defining); +localVisibility (Injector requesting, Injector defining) => + identical(skipShadow(requesting), defining); directChildrenVisibility(Injector requesting, Injector defining) { requesting = skipShadow(requesting); return identical(requesting.parent, defining) || localVisibility(requesting, defining); } -Directive cloneWithNewMap(Directive annotation, map) - => annotation._cloneWithNewMap(map); +Directive cloneWithNewMap(Directive annotation, map) => annotation._cloneWithNewMap(map); String mappingSpec(DirectiveAnnotation annotation) => annotation._mappingSpec; @@ -69,30 +68,11 @@ abstract class Directive { * Specifies the compiler action to be taken on the child nodes of the * element which this currently being compiled. The values are: * - * * [COMPILE_CHILDREN] (*default*) - * * [TRANSCLUDE_CHILDREN] - * * [IGNORE_CHILDREN] + * * [:true:] Compile the child nodes of the element. (default) + * * [:false:] Do not compile/visit the child nodes. Angular markup on + * descendant nodes will not be processed. */ - @deprecated - final String children; - - /** - * Compile the child nodes of the element. This is the default. - */ - @deprecated - static const String COMPILE_CHILDREN = 'compile'; - /** - * Compile the child nodes for transclusion and makes available - * [BoundViewFactory], [ViewFactory] and [ViewPort] for injection. - */ - @deprecated - static const String TRANSCLUDE_CHILDREN = 'transclude'; - /** - * Do not compile/visit the child nodes. Angular markup on descendant nodes - * will not be processed. - */ - @deprecated - static const String IGNORE_CHILDREN = 'ignore'; + final bool compileChildren; /** * A directive/component controller class can be injected into other @@ -123,7 +103,7 @@ abstract class Directive { * module: Foo.moduleFactory) * class Foo { * static moduleFactory() => new Module() - * ..bind(SomeTypeA, visibility: Directive.LOCAL_VISIBILITY); + * ..bind(SomeTypeA, visibility: Directive.LOCAL_VISIBILITY); * } * * When specifying types, factories or values in the module, notice that @@ -215,7 +195,7 @@ abstract class Directive { const Directive({ this.selector, - this.children: Directive.COMPILE_CHILDREN, + this.compileChildren: true, this.visibility: Directive.LOCAL_VISIBILITY, this.module, this.map: const {}, @@ -223,10 +203,11 @@ abstract class Directive { this.exportExpressionAttrs: const [] }); - toString() => selector; - get hashCode => selector.hashCode; - operator==(other) => - other is Directive && selector == other.selector; + String toString() => selector; + + int get hashCode => selector.hashCode; + + bool operator==(other) => other is Directive && selector == other.selector; Directive _cloneWithNewMap(newMap); } @@ -333,7 +314,7 @@ class Component extends Directive { _applyAuthorStyles = applyAuthorStyles, _resetStyleInheritance = resetStyleInheritance, super(selector: selector, - children: Directive.COMPILE_CHILDREN, + compileChildren: true, visibility: visibility, map: map, module: module, @@ -344,7 +325,7 @@ class Component extends Directive { const [] : _cssUrls is List ? _cssUrls : [_cssUrls]; - Directive _cloneWithNewMap(newMap) => + Component _cloneWithNewMap(newMap) => new Component( template: template, templateUrl: templateUrl, @@ -375,7 +356,7 @@ class Component extends Directive { * * `detach()` - Called on when owning scope is destroyed. */ class Decorator extends Directive { - const Decorator({children: Directive.COMPILE_CHILDREN, + const Decorator({compileChildren: true, map, selector, module, @@ -383,16 +364,16 @@ class Decorator extends Directive { exportExpressions, exportExpressionAttrs}) : super(selector: selector, - children: children, + compileChildren: compileChildren, visibility: visibility, map: map, module: module, exportExpressions: exportExpressions, exportExpressionAttrs: exportExpressionAttrs); - Directive _cloneWithNewMap(newMap) => + Decorator _cloneWithNewMap(newMap) => new Decorator( - children: children, + compileChildren: compileChildren, map: newMap, module: module, selector: selector, @@ -401,6 +382,45 @@ class Decorator extends Directive { exportExpressionAttrs: exportExpressionAttrs); } + + +/** +* Meta-data marker placed on a class which should act as template. +* +* Angular templates are instantiated using dependency injection, and can +* ask for any injectable object in their constructor. Templates can also ask +* for other components or directives declared on the DOM element. +* +* Templates can implement [NgAttachAware], [NgDetachAware] and declare these +* optional methods: +* +* * `attach()` - Called on first [Scope.apply()]. +* * `detach()` - Called on when owning scope is destroyed. +*/ +class Template extends Directive { + const Template({map, + selector, + module, + visibility, + exportExpressions, + exportExpressionAttrs}) + : super(selector: selector, + compileChildren: true, + visibility: visibility, + map: map, + module: module, + exportExpressions: exportExpressions, + exportExpressionAttrs: exportExpressionAttrs); + + Template _cloneWithNewMap(newMap) => + new Template(map: newMap, + module: module, + selector: selector, + visibility: visibility, + exportExpressions: exportExpressions, + exportExpressionAttrs: exportExpressionAttrs); +} + /** * Meta-data marker placed on a class which should act as a controller for your * application. @@ -428,7 +448,7 @@ class Controller extends Decorator { final String publishAs; const Controller({ - children: Directive.COMPILE_CHILDREN, + compileChildren: true, this.publishAs, map, module, @@ -438,7 +458,7 @@ class Controller extends Decorator { exportExpressionAttrs }) : super(selector: selector, - children: children, + compileChildren: compileChildren, visibility: visibility, map: map, module: module, @@ -447,7 +467,7 @@ class Controller extends Decorator { Directive _cloneWithNewMap(newMap) => new Controller( - children: children, + compileChildren: compileChildren, publishAs: publishAs, module: module, map: newMap, diff --git a/lib/core/registry.dart b/lib/core/registry.dart index 9d66de3ed..c9148855a 100644 --- a/lib/core/registry.dart +++ b/lib/core/registry.dart @@ -42,20 +42,20 @@ abstract class AnnotationsMap { extractMetadata(type) .where((annotation) => annotation is K) .forEach((annotation) { - map.putIfAbsent(annotation, () => []).add(type); + map.putIfAbsent(annotation, () => []).add(type); }); }); } - List operator[](K annotation) { + List operator[](K annotation) { var value = map[annotation]; if (value == null) throw 'No $annotation found!'; return value; } void forEach(fn(K, Type)) { - map.forEach((annotation, types) { - types.forEach((type) { + map.forEach((K annotation, List types) { + types.forEach((Type type) { fn(annotation, type); }); }); @@ -63,8 +63,8 @@ abstract class AnnotationsMap { List annotationsFor(Type type) { var res = []; - forEach((ann, annType) { - if (annType == type) res.add(ann); + map.forEach((K ann, List types) { + if (types.contains(type)) res.add(ann); }); return res; } diff --git a/lib/core/registry_dynamic.dart b/lib/core/registry_dynamic.dart index 54ea6573d..7342ba3cd 100644 --- a/lib/core/registry_dynamic.dart +++ b/lib/core/registry_dynamic.dart @@ -7,9 +7,9 @@ import 'package:angular/core/registry.dart'; export 'package:angular/core/registry.dart' show MetadataExtractor; -var _fieldMetadataCache = new Map>(); - class DynamicMetadataExtractor implements MetadataExtractor { + static final _fieldMetadataCache = >{}; + final _fieldAnnotations = [ reflectType(NgAttr), reflectType(NgOneWay), @@ -24,29 +24,28 @@ class DynamicMetadataExtractor implements MetadataExtractor { if (metadata == null) { metadata = []; } else { - metadata = metadata.map((InstanceMirror im) => map(type, im.reflectee)); + metadata = metadata.map((InstanceMirror im) => _mergeMap(type, im.reflectee)); } return metadata; } - map(Type type, obj) { - if (obj is Directive) { - return mapDirectiveAnnotation(type, obj); - } else { - return obj; - } - } - - Directive mapDirectiveAnnotation(Type type, Directive annotation) { - var match; - var fieldMetadata = fieldMetadataExtractor(type); - if (fieldMetadata.isNotEmpty) { - var newMap = annotation.map == null ? {} : new Map.from(annotation.map); - fieldMetadata.forEach((String fieldName, DirectiveAnnotation ann) { + /** + * Merges the field annotations with the [AbstractNgAttrAnnotation.map] + * definition from the [Directive]. + * + * [_mergeDirectiveMap] throws when the definition for an annotated is + * duplicated in the [AbstractNgAttrAnnotation.map] + */ + dynamic _mergeMap(Type type, annotation) { + if (annotation is! Directive) return annotation; + var metaData = _extractFieldMetadata(type); + if (metaData.isNotEmpty) { + var newMap = annotation.map == null ? {} : new Map.from(annotation.map); + metaData.forEach((String fieldName, DirectiveAnnotation ann) { var attrName = ann.attrName; if (newMap.containsKey(attrName)) { throw 'Mapping for attribute $attrName is already defined (while ' - 'processing annottation for field $fieldName of $type)'; + 'processing annotation for field $fieldName of $type)'; } newMap[attrName] = '${mappingSpec(ann)}$fieldName'; }); @@ -55,21 +54,17 @@ class DynamicMetadataExtractor implements MetadataExtractor { return annotation; } - - Map fieldMetadataExtractor(Type type) => + Map _extractFieldMetadata(Type type) => _fieldMetadataCache.putIfAbsent(type, () => _fieldMetadataExtractor(reflectType(type))); + /// Extract metadata defined on fields via a [DirectiveAnnotation] Map _fieldMetadataExtractor(ClassMirror cm) { var fields = {}; - if(cm.superclass != null) { - fields.addAll(_fieldMetadataExtractor(cm.superclass)); - } else { - fields = {}; - } + if(cm.superclass != null) fields.addAll(_fieldMetadataExtractor(cm.superclass)); + Map declarations = cm.declarations; - declarations.forEach((symbol, dm) { - if(dm is VariableMirror || - dm is MethodMirror && (dm.isGetter || dm.isSetter)) { + declarations.forEach((Symbol symbol, DeclarationMirror dm) { + if (dm is VariableMirror || dm is MethodMirror && (dm.isGetter || dm.isSetter)) { var fieldName = MirrorSystem.getName(symbol); if (dm is MethodMirror && dm.isSetter) { // Remove "=" from the end of the setter. @@ -79,7 +74,7 @@ class DynamicMetadataExtractor implements MetadataExtractor { if (_fieldAnnotations.contains(meta.type)) { if (fields.containsKey(fieldName)) { throw 'Attribute annotation for $fieldName is defined more ' - 'than once in ${cm.reflectedType}'; + 'than once in ${cm.reflectedType}'; } fields[fieldName] = meta.reflectee as DirectiveAnnotation; } diff --git a/lib/core/scope.dart b/lib/core/scope.dart index 155c9f141..b56890c20 100644 --- a/lib/core/scope.dart +++ b/lib/core/scope.dart @@ -228,7 +228,7 @@ class Scope { } else if (expression.startsWith(':')) { expression = expression.substring(1); fn = (value, last) { - if (value != null) reactionFn(value, last); + if (value != null) reactionFn(value, last); }; } } diff --git a/lib/core_dom/common.dart b/lib/core_dom/common.dart index a60a050ee..5e184b8ae 100644 --- a/lib/core_dom/common.dart +++ b/lib/core_dom/common.dart @@ -1,8 +1,7 @@ part of angular.core.dom_internal; -List cloneElements(elements) { - return elements.map((el) => el.clone(true)).toList(); -} +List cloneElements(elements) => + elements.map((el) => el.clone(true)).toList(); class MappingParts { final String attrName; @@ -19,8 +18,18 @@ class DirectiveRef { final Directive annotation; final String value; final mappings = new List(); - - DirectiveRef(this.element, this.type, this.annotation, [ this.value ]); + Map _templateAttrs; + Map get templateAttrs => _templateAttrs; + + DirectiveRef(this.element, this.type, this.annotation, [ this.value ]) { + if (annotation is Template && annotation.map != null) { + var attributes = (element as dom.Element).attributes; + _templateAttrs = {}; + annotation.map.keys.forEach((attrName) { + _templateAttrs[attrName] = attributes[attrName]; + }); + } + } String toString() { var html = element is dom.Element diff --git a/lib/core_dom/directive_map.dart b/lib/core_dom/directive_map.dart index 0e92c21b2..e70ade7f5 100644 --- a/lib/core_dom/directive_map.dart +++ b/lib/core_dom/directive_map.dart @@ -2,11 +2,13 @@ part of angular.core.dom_internal; @Injectable() class DirectiveMap extends AnnotationsMap { - DirectiveSelectorFactory _directiveSelectorFactory; + final DirectiveSelectorFactory _directiveSelectorFactory; DirectiveSelector _selector; DirectiveSelector get selector { - if (_selector != null) return _selector; - return _selector = _directiveSelectorFactory.selector(this); + if (_selector == null) { + _selector = _directiveSelectorFactory.selector(this); + } + return _selector; } DirectiveMap(Injector injector, diff --git a/lib/core_dom/element_binder.dart b/lib/core_dom/element_binder.dart index bc562c675..89c84e1c6 100644 --- a/lib/core_dom/element_binder.dart +++ b/lib/core_dom/element_binder.dart @@ -58,26 +58,25 @@ class ElementBinder { final DirectiveRef component; - // Can be either COMPILE_CHILDREN or IGNORE_CHILDREN - final String childMode; + final bool compileChildren; ElementBinder(this._perf, this._expando, this._parser, this._componentFactory, this._transcludingComponentFactory, this._shadowDomComponentFactory, this.component, this.decorators, - this.onEvents, this.bindAttrs, this.childMode); + this.onEvents, this.bindAttrs, this.compileChildren); final bool hasTemplate = false; - bool get shouldCompileChildren => - childMode == Directive.COMPILE_CHILDREN; - var _directiveCache; List get _usableDirectiveRefs { - if (_directiveCache != null) return _directiveCache; - if (component != null) return _directiveCache = new List.from(decorators)..add(component); - return _directiveCache = decorators; + if (_directiveCache == null) { + _directiveCache = component != null ? + (new List.from(decorators)..add(component)) : + decorators; + } + return _directiveCache; } bool get hasDirectivesOrEvents => @@ -124,11 +123,19 @@ class ElementBinder { dstPathFn.assign(controller, _parser(expression).bind(scope.context, ScopeLocals.wrapper)); } - _createAttrMappings(controller, scope, List mappings, nodeAttrs, formatters, tasks) { - mappings.forEach((MappingParts p) { + _createAttrMappings(controller, scope, DirectiveRef ref, nodeAttrs, formatters, tasks) { + ref.mappings.forEach((MappingParts p) { var attrName = p.attrName; var dstExpression = p.dstExpression; + var attrValue; + if (nodeAttrs == null) { + assert(ref.annotation is Template); + attrValue = ref._templateAttrs[attrName]; + } else { + attrValue = nodeAttrs[attrName]; + } + Expression dstPathFn = _parser(dstExpression); if (!dstPathFn.isAssignable) { throw "Expression '$dstExpression' is not assignable in mapping '${p.originalValue}' " @@ -139,8 +146,7 @@ class ElementBinder { var bindAttr = bindAttrs["bind-${p.attrName}"]; if (bindAttr != null) { if (p.mode == '<=>') { - _bindTwoWay(tasks, bindAttr, scope, dstPathFn, - controller, formatters, dstExpression); + _bindTwoWay(tasks, bindAttr, scope, dstPathFn, controller, formatters, dstExpression); } else if(p.mode == '&') { _bindCallback(dstPathFn, controller, bindAttr, scope); } else { @@ -152,29 +158,32 @@ class ElementBinder { switch (p.mode) { case '@': // string var taskId = tasks.registerTask(); - nodeAttrs.observe(attrName, (value) { - dstPathFn.assign(controller, value); + if (nodeAttrs == null) { + dstPathFn.assign(controller, attrValue); tasks.completeTask(taskId); - }); + } else { + nodeAttrs.observe(attrName, (value) { + dstPathFn.assign(controller, value); + tasks.completeTask(taskId); + }); + } break; case '<=>': // two-way - if (nodeAttrs[attrName] == null) return; + if (attrValue == null) return; - _bindTwoWay(tasks, nodeAttrs[attrName], scope, dstPathFn, - controller, formatters, dstExpression); + _bindTwoWay(tasks, attrValue, scope, dstPathFn, controller, formatters, dstExpression); break; case '=>': // one-way - if (nodeAttrs[attrName] == null) return; - _bindOneWay(tasks, nodeAttrs[attrName], scope, - dstPathFn, controller, formatters); + if (attrValue == null) return; + _bindOneWay(tasks, attrValue, scope, dstPathFn, controller, formatters); break; case '=>!': // one-way, one-time - if (nodeAttrs[attrName] == null) return; + if (attrValue == null) return; - Expression attrExprFn = _parser(nodeAttrs[attrName]); + Expression attrExprFn = _parser(attrValue); var watch; watch = scope.watch(nodeAttrs[attrName], (value, _) { if (dstPathFn.assign(controller, value) != null) { @@ -184,7 +193,7 @@ class ElementBinder { break; case '&': // callback - _bindCallback(dstPathFn, controller, nodeAttrs[attrName], scope); + _bindCallback(dstPathFn, controller, attrValue, scope); break; } }); @@ -209,18 +218,16 @@ class ElementBinder { } : null); if (ref.mappings.isNotEmpty) { - if (nodeAttrs == null) nodeAttrs = new _AnchorAttrs(ref); - _createAttrMappings(controller, scope, ref.mappings, nodeAttrs, formatters, tasks); + _createAttrMappings(controller, scope, ref, nodeAttrs, formatters, tasks); } if (controller is AttachAware) { var taskId = tasks.registerTask(); Watch watch; - watch = scope.watch('1', // Cheat a bit. + watch = scope.watch('::1', // Cheat a bit. (_, __) { - watch.remove(); - tasks.completeTask(taskId); - }); + tasks.completeTask(taskId); + }); } tasks.doneRegistering(); @@ -339,12 +346,12 @@ class ElementBinder { * Private class used for managing controller.attach() calls */ class _TaskList { - var onDone; + final Function _onDone; final List _tasks = []; bool isDone = false; - _TaskList(this.onDone) { - if (onDone == null) isDone = true; + _TaskList(this._onDone) { + if (_onDone == null) isDone = true; } int registerTask() { @@ -357,12 +364,12 @@ class _TaskList { if (isDone) return; _tasks[id] = true; if (_tasks.every((a) => a)) { - onDone(); + _onDone(); isDone = true; } } - doneRegistering() { + void doneRegistering() { completeTask(registerTask()); } } diff --git a/lib/core_dom/element_binder_builder.dart b/lib/core_dom/element_binder_builder.dart index 050c53c18..27fdeb8c9 100644 --- a/lib/core_dom/element_binder_builder.dart +++ b/lib/core_dom/element_binder_builder.dart @@ -18,11 +18,12 @@ class ElementBinderFactory { ElementBinder binder(ElementBinderBuilder b) => new ElementBinder(_perf, _expando, _parser, _componentFactory, _transcludingComponentFactory, _shadowDomComponentFactory, - b.component, b.decorators, b.onEvents, b.bindAttrs, b.childMode); + b.component, b.decorators, b.onEvents, b.bindAttrs, b.compileChildren); + TemplateElementBinder templateBinder(ElementBinderBuilder b, ElementBinder transclude) => new TemplateElementBinder(_perf, _expando, _parser, _componentFactory, _transcludingComponentFactory, _shadowDomComponentFactory, - b.template, transclude, b.onEvents, b.bindAttrs, b.childMode); + b.template, transclude, b.onEvents, b.bindAttrs, b.compileChildren); } /** @@ -37,55 +38,49 @@ class ElementBinderBuilder { final onEvents = {}; final bindAttrs = {}; - var decorators = []; - DirectiveRef template; ViewFactory templateViewFactory; + bool isTemplate = false; + var decorators = []; DirectiveRef component; + DirectiveRef template; - // Can be either COMPILE_CHILDREN or IGNORE_CHILDREN - String childMode = Directive.COMPILE_CHILDREN; + bool compileChildren = true; ElementBinderBuilder(this._factory); addDirective(DirectiveRef ref) { var annotation = ref.annotation; - var children = annotation.children; + compileChildren = compileChildren && annotation.compileChildren; - if (annotation.children == Directive.TRANSCLUDE_CHILDREN) { + if (annotation is Template) { template = ref; + isTemplate = true; } else if (annotation is Component) { component = ref; } else { decorators.add(ref); } - if (annotation.children == Directive.IGNORE_CHILDREN) { - childMode = annotation.children; - } - if (annotation.map != null) annotation.map.forEach((attrName, mapping) { Match match = _MAPPING.firstMatch(mapping); - if (match == null) { - throw "Unknown mapping '$mapping' for attribute '$attrName'."; - } + if (match == null) throw "Unknown mapping '$mapping' for attribute '$attrName'."; + var mode = match[1]; var dstPath = match[2]; - String dstExpression = dstPath.isEmpty ? attrName : dstPath; + if (dstPath.isEmpty) dstPath = attrName; - ref.mappings.add(new MappingParts(attrName, mode, dstExpression, mapping)); + ref.mappings.add(new MappingParts(attrName, mode, dstPath, mapping)); }); } ElementBinder get binder { - if (template != null) { + if (isTemplate) { var transclude = _factory.binder(this); return _factory.templateBinder(this, transclude); - } else { return _factory.binder(this); } - } } diff --git a/lib/core_dom/node_cursor.dart b/lib/core_dom/node_cursor.dart index a88fe2dfe..85f40dc77 100644 --- a/lib/core_dom/node_cursor.dart +++ b/lib/core_dom/node_cursor.dart @@ -12,12 +12,11 @@ class NodeCursor { dom.Node get current => index < elements.length ? elements[index] : null; bool descend() { - var childNodes = elements[index].nodes; - var hasChildren = childNodes != null && childNodes.isNotEmpty; + var hasChildren = elements[index].hasChildNodes(); if (hasChildren) { stack..add(index)..add(elements); - elements = new List.from(childNodes); + elements = new List.from(elements[index].nodes); index = 0; } @@ -45,5 +44,5 @@ class NodeCursor { NodeCursor remove() => new NodeCursor([elements.removeAt(index)..remove()]); - toString() => "[NodeCursor: $elements $index]"; + String toString() => "[NodeCursor: $elements $index]"; } diff --git a/lib/core_dom/selector.dart b/lib/core_dom/selector.dart index fec6946e8..0f595b5f0 100644 --- a/lib/core_dom/selector.dart +++ b/lib/core_dom/selector.dart @@ -116,11 +116,11 @@ class DirectiveSelector { elementSelectors.forEach((_ElementSelector elementSelector) { classes.forEach((className, _) { partialSelection = elementSelector.selectClass(builder, - partialSelection, node, className); + partialSelection, node, className); }); attrs.forEach((attrName, value) { partialSelection = elementSelector.selectAttr(builder, - partialSelection, node, attrName, value); + partialSelection, node, attrName, value); }); }); } @@ -152,7 +152,7 @@ class DirectiveSelector { */ @Injectable() class DirectiveSelectorFactory { - ElementBinderFactory _binderFactory; + final ElementBinderFactory _binderFactory; DirectiveSelectorFactory(this._binderFactory); @@ -166,7 +166,7 @@ class _Directive { _Directive(this.type, this.annotation); - toString() => annotation.selector; + String toString() => annotation.selector; } class _ContainsSelector { @@ -198,7 +198,7 @@ class _SelectorPart { const _SelectorPart.fromAttribute(this.attrName, this.attrValue) : element = null, className = null; - toString() => + String toString() => element == null ? (className == null ? (attrValue == '' ? '[$attrName]' : '[$attrName=$attrValue]') @@ -344,7 +344,7 @@ class _ElementSelector { () => new RegExp('^${key.replaceAll('*', r'[\w\-]+')}\$')) .hasMatch(attrName), orElse: () => null); - toString() => 'ElementSelector($name)'; + String toString() => 'ElementSelector($name)'; } List<_SelectorPart> _splitCss(String selector, Type type) { diff --git a/lib/core_dom/tagging_compiler.dart b/lib/core_dom/tagging_compiler.dart index a03007428..2143e740d 100644 --- a/lib/core_dom/tagging_compiler.dart +++ b/lib/core_dom/tagging_compiler.dart @@ -60,7 +60,7 @@ class TaggingCompiler implements Compiler { taggedElementBinderIndex = parentElementBinderOffset; } - if (elementBinder.shouldCompileChildren) { + if (elementBinder.compileChildren) { if (domCursor.descend()) { var addedDummy = false; if (taggedElementBinder == null) { diff --git a/lib/core_dom/tagging_view_factory.dart b/lib/core_dom/tagging_view_factory.dart index d6ebe1bbf..2fb50b56f 100644 --- a/lib/core_dom/tagging_view_factory.dart +++ b/lib/core_dom/tagging_view_factory.dart @@ -7,8 +7,7 @@ class TaggingViewFactory implements ViewFactory { TaggingViewFactory(this.templateNodes, this.elementBinders, this._perf); - BoundViewFactory bind(Injector injector) => - new BoundViewFactory(this, injector); + BoundViewFactory bind(Injector injector) => new BoundViewFactory(this, injector); View call(Injector injector, [List nodes /* TODO: document fragment */]) { if (nodes == null) { @@ -27,10 +26,14 @@ class TaggingViewFactory implements ViewFactory { _bindTagged(TaggedElementBinder tagged, rootInjector, elementBinders, View view, boundNode) { var binder = tagged.binder; - var parentInjector = tagged.parentBinderOffset == -1 ? rootInjector : elementBinders[tagged.parentBinderOffset].injector; + var parentInjector = tagged.parentBinderOffset == -1 ? + rootInjector : + elementBinders[tagged.parentBinderOffset].injector; assert(parentInjector != null); - tagged.injector = binder != null ? binder.bind(view, parentInjector, boundNode) : parentInjector; + tagged.injector = binder != null ? + binder.bind(view, parentInjector, boundNode) : + parentInjector; if (tagged.textBinders != null) { for (var k = 0, kk = tagged.textBinders.length; k < kk; k++) { diff --git a/lib/core_dom/view.dart b/lib/core_dom/view.dart index c53309f7d..8be3b19ea 100644 --- a/lib/core_dom/view.dart +++ b/lib/core_dom/view.dart @@ -38,7 +38,7 @@ class ViewPort { _viewsInsertAfter(view, insertAfter); _animate.insert(view.nodes, placeholder.parentNode, - insertBefore: previousNode.nextNode); + insertBefore: previousNode.nextNode); } void remove(View view) { diff --git a/lib/core_dom/view_factory.dart b/lib/core_dom/view_factory.dart index 203258feb..087551c67 100644 --- a/lib/core_dom/view_factory.dart +++ b/lib/core_dom/view_factory.dart @@ -143,18 +143,6 @@ class ViewCache { } } -class _AnchorAttrs extends NodeAttrs { - DirectiveRef _directiveRef; - - _AnchorAttrs(DirectiveRef this._directiveRef): super(null); - - String operator [](name) => name == '.' ? _directiveRef.value : null; - - void observe(String attributeName, _AttributeChanged notifyFn) { - notifyFn(attributeName == '.' ? _directiveRef.value : null); - } -} - String _html(obj) { if (obj is String) { return obj; diff --git a/lib/core_dom/walking_compiler.dart b/lib/core_dom/walking_compiler.dart index fecd52dda..e211afb00 100644 --- a/lib/core_dom/walking_compiler.dart +++ b/lib/core_dom/walking_compiler.dart @@ -45,7 +45,7 @@ class WalkingCompiler implements Compiler { templateBinder.template, templateBinder.templateBinder, directives); } - if (elementBinder.shouldCompileChildren) { + if (elementBinder.compileChildren) { if (domCursor.descend()) { templateCursor.descend(); diff --git a/lib/directive/ng_if.dart b/lib/directive/ng_if.dart index 562bfa181..4e1719005 100644 --- a/lib/directive/ng_if.dart +++ b/lib/directive/ng_if.dart @@ -89,10 +89,9 @@ abstract class _NgUnlessIfAttrDirectiveBase { * * */ -@Decorator( - children: Directive.TRANSCLUDE_CHILDREN, +@Template( selector:'[ng-if]', - map: const {'.': '=>condition'}) + map: const {'ng-if': '=>condition'}) class NgIf extends _NgUnlessIfAttrDirectiveBase { NgIf(BoundViewFactory boundViewFactory, ViewPort viewPort, @@ -150,10 +149,9 @@ class NgIf extends _NgUnlessIfAttrDirectiveBase { * * */ -@Decorator( - children: Directive.TRANSCLUDE_CHILDREN, +@Template( selector:'[ng-unless]', - map: const {'.': '=>condition'}) + map: const {'ng-unless': '=>condition'}) class NgUnless extends _NgUnlessIfAttrDirectiveBase { NgUnless(BoundViewFactory boundViewFactory, diff --git a/lib/directive/ng_non_bindable.dart b/lib/directive/ng_non_bindable.dart index 67695b8b9..3318cf37f 100644 --- a/lib/directive/ng_non_bindable.dart +++ b/lib/directive/ng_non_bindable.dart @@ -20,5 +20,5 @@ part of angular.directive; */ @Decorator( selector: '[ng-non-bindable]', - children: Directive.IGNORE_CHILDREN) + compileChildren: false) class NgNonBindable {} diff --git a/lib/directive/ng_repeat.dart b/lib/directive/ng_repeat.dart index 99e7d93e9..2124cb2f8 100644 --- a/lib/directive/ng_repeat.dart +++ b/lib/directive/ng_repeat.dart @@ -65,10 +65,9 @@ part of angular.directive; * */ -@Decorator( - children: Directive.TRANSCLUDE_CHILDREN, +@Template( selector: '[ng-repeat]', - map: const {'.': '@expression'}) + map: const {'ng-repeat': '@expression'}) class NgRepeat { static RegExp _SYNTAX = new RegExp(r'^\s*(.+)\s+in\s+(.*?)\s*(?:track\s+by\s+(.+)\s*)?(\s+lazily\s*)?$'); static RegExp _LHS_SYNTAX = new RegExp(r'^(?:([$\w]+)|\(([$\w]+)\s*,\s*([$\w]+)\))$'); diff --git a/lib/directive/ng_switch.dart b/lib/directive/ng_switch.dart index c9aec1275..67e977007 100644 --- a/lib/directive/ng_switch.dart +++ b/lib/directive/ng_switch.dart @@ -109,10 +109,9 @@ class _Case { _Case(this.anchor, this.viewFactory); } -@Decorator( +@Template( selector: '[ng-switch-when]', - children: Directive.TRANSCLUDE_CHILDREN, - map: const {'.': '@value'}) + map: const {'ng-switch-when': '@value'}) class NgSwitchWhen { final NgSwitch ngSwitch; final ViewPort port; @@ -124,9 +123,7 @@ class NgSwitchWhen { set value(String value) => ngSwitch.addCase('!$value', port, viewFactory); } -@Decorator( - children: Directive.TRANSCLUDE_CHILDREN, - selector: '[ng-switch-default]') +@Template(selector: '[ng-switch-default]') class NgSwitchDefault { NgSwitchDefault(NgSwitch ngSwitch, ViewPort port, diff --git a/lib/directive/ng_template.dart b/lib/directive/ng_template.dart index 969df2054..1aecdf481 100644 --- a/lib/directive/ng_template.dart +++ b/lib/directive/ng_template.dart @@ -23,7 +23,7 @@ part of angular.directive; map: const {'id': '@templateUrl'}) @Decorator( selector: 'script[type=text/ng-template]', - children: Directive.IGNORE_CHILDREN, + compileChildren: false, map: const {'id': '@templateUrl'}) class NgTemplate { final dom.Element element; diff --git a/lib/tools/source_metadata_extractor.dart b/lib/tools/source_metadata_extractor.dart index 6d209ba9a..177bca0df 100644 --- a/lib/tools/source_metadata_extractor.dart +++ b/lib/tools/source_metadata_extractor.dart @@ -78,12 +78,11 @@ class SourceMetadataExtractor { substring(0, className.length - _COMPONENT.length); } else { throw "Directive name '$className' must end with $_DIRECTIVE, " - "$_ATTR_DIRECTIVE, $_COMPONENT or have a \$selector field."; + "$_ATTR_DIRECTIVE, $_COMPONENT or have a \$selector field."; } } else { if (className.endsWith(_ATTR_DIRECTIVE)) { - var attrName = className. - substring(0, className.length - _ATTR_DIRECTIVE.length); + var attrName = className.substring(0, className.length - _ATTR_DIRECTIVE.length); dirInfo.selector = '[$attrName]'; } else if (className.endsWith(_DIRECTIVE)) { dirInfo.selector = className. @@ -139,13 +138,14 @@ class DirectiveMetadataCollectingAstVisitor extends RecursiveAstVisitor { } visitClassDeclaration(ClassDeclaration clazz) { - // Check class annotations for presense of Component/Decorator. + // Check class annotations for presence of Component or Decorator. clazz.metadata.forEach((Annotation ann) { if (ann.arguments == null) return; // Ignore non-class annotations. // TODO(pavelj): this is not a safe check for the type of the // annotations, but good enough for now. - if (ann.name.name != 'Component' - && ann.name.name != 'Decorator') return; + if (ann.name.name != 'Component' && + ann.name.name != 'Decorator' && + ann.name.name != 'Template') return; bool isComponent = ann.name.name == 'Component'; @@ -158,24 +158,26 @@ class DirectiveMetadataCollectingAstVisitor extends RecursiveAstVisitor { if (arg is NamedExpression) { NamedExpression namedArg = arg; var paramName = namedArg.name.label.name; - if (paramName == 'selector') { - meta.selector = assertString(namedArg.expression).stringValue; - } - if (paramName == 'template') { - meta.template = assertString(namedArg.expression).stringValue; - } - if (paramName == 'map') { - MapLiteral map = namedArg.expression; - map.entries.forEach((MapLiteralEntry entry) { - meta.attributeMappings[assertString(entry.key).stringValue] = - assertString(entry.value).stringValue; - }); - } - if (paramName == 'exportExpressions') { - meta.exportExpressions = getStringValues(namedArg.expression); - } - if (paramName == 'exportExpressionAttrs') { - meta.exportExpressionAttrs = getStringValues(namedArg.expression); + switch (paramName) { + case 'selector': + meta.selector = assertString(namedArg.expression).stringValue; + break; + case 'template': + meta.template = assertString(namedArg.expression).stringValue; + break; + case 'map': + MapLiteral map = namedArg.expression; + map.entries.forEach((MapLiteralEntry entry) { + meta.attributeMappings[assertString(entry.key).stringValue] = + assertString(entry.value).stringValue; + }); + break; + case 'exportExpressions': + meta.exportExpressions = getStringValues(namedArg.expression); + break; + case 'exportExpressionAttrs': + meta.exportExpressionAttrs = getStringValues(namedArg.expression); + break; } } }); @@ -202,8 +204,7 @@ class DirectiveMetadataCollectingAstVisitor extends RecursiveAstVisitor { // Check fields/getters/setter for presence of attr mapping annotations. clazz.members.forEach((ClassMember member) { if (member is FieldDeclaration || - (member is MethodDeclaration && - (member.isSetter || member.isGetter))) { + (member is MethodDeclaration && (member.isSetter || member.isGetter))) { member.metadata.forEach((Annotation ann) { if (_attrAnnotationsToSpec.containsKey(ann.name.name)) { String fieldName; @@ -213,13 +214,11 @@ class DirectiveMetadataCollectingAstVisitor extends RecursiveAstVisitor { fieldName = (member as MethodDeclaration).name.name; } StringLiteral attNameLiteral = ann.arguments.arguments.first; - if (meta.attributeMappings - .containsKey(attNameLiteral.stringValue)) { - throw 'Attribute mapping already defined for ' - '${clazz.name}.$fieldName'; + if (meta.attributeMappings.containsKey(attNameLiteral.stringValue)) { + throw 'Attribute mapping already defined for ${clazz.name}.$fieldName'; } meta.attributeMappings[attNameLiteral.stringValue] = - _attrAnnotationsToSpec[ann.name.name] + fieldName; + _attrAnnotationsToSpec[ann.name.name] + fieldName; } }); } diff --git a/lib/transformer.dart b/lib/transformer.dart index 0d8668203..cb0d42ebf 100644 --- a/lib/transformer.dart +++ b/lib/transformer.dart @@ -36,6 +36,7 @@ TransformOptions _parseSettings(Map args) { var annotations = [ 'angular.core.annotation_src.Injectable', 'angular.core.annotation_src.Decorator', + 'angular.core.annotation_src.Template', 'angular.core.annotation_src.Controller', 'angular.core.annotation_src.Component', 'angular.core.annotation_src.Formatter']; diff --git a/test/angular_spec.dart b/test/angular_spec.dart index 8efc3aa69..4abc4dd40 100644 --- a/test/angular_spec.dart +++ b/test/angular_spec.dart @@ -109,6 +109,7 @@ main() { "angular.core.annotation_src.NgOneWay", "angular.core.annotation_src.NgOneWayOneTime", "angular.core.annotation_src.NgTwoWay", + "angular.core.annotation_src.Template", "angular.core.dom_internal.Animate", "angular.core.dom_internal.Animation", "angular.core.dom_internal.AnimationResult", diff --git a/test/core/annotation_src_spec.dart b/test/core/annotation_src_spec.dart index 2bfeafce3..8a4710c51 100644 --- a/test/core/annotation_src_spec.dart +++ b/test/core/annotation_src_spec.dart @@ -60,7 +60,7 @@ void main() => describe('annotations', () { describe('decorator', () { it('should set all fields on clone when all the fields are set', () { var decorator = new Decorator( - children: 'xxx', + compileChildren: false, map: {}, selector: '', module: (){}, @@ -77,11 +77,30 @@ void main() => describe('annotations', () { }); }); + describe('template', () { + it('should set all fields on clone when all the fields are set', () { + var template = new Template( + map: {}, + selector: '', + module: (){}, + visibility: Directive.LOCAL_VISIBILITY, + exportExpressions: [], + exportExpressionAttrs: [] + ); + + // Check that no fields are null + expect(nullFields(template)).toEqual([]); + + // Check that the clone is the same as the original. + expect(variables(cloneWithNewMap(template, {}))).toEqual(variables(template)); + }); + }); + describe('controller', () { it('should set all fields on clone when all the fields are set', () { var controller = new Controller( publishAs: '', - children: 'xxx', + compileChildren: false, map: {}, selector: '', module: (){}, diff --git a/test/core/core_directive_spec.dart b/test/core/core_directive_spec.dart index ab4cd3149..86742997d 100644 --- a/test/core/core_directive_spec.dart +++ b/test/core/core_directive_spec.dart @@ -4,10 +4,11 @@ import '../_specs.dart'; import 'package:angular/application_factory.dart'; void main() { - describe('DirectiveMap', () { + describe('DirectiveMap on @Component and @Decorator', () { beforeEachModule((Module module) { - module..bind(AnnotatedIoComponent); + module..bind(AnnotatedIoComponent) + ..type(AnnotatedTemplate); }); it('should extract attr map from annotated component', (DirectiveMap directives) { @@ -36,6 +37,28 @@ void main() { }); }); + it('should extract attr map from annotated template', (DirectiveMap directives) { + var annotations = directives.annotationsFor(AnnotatedTemplate); + expect(annotations.length).toEqual(1); + expect(annotations[0] is Template).toBeTruthy(); + + Template annotation = annotations[0]; + expect(annotation.selector).toEqual('[template]'); + expect(annotation.visibility).toEqual(Directive.LOCAL_VISIBILITY); + expect(annotation.exportExpressions).toEqual(['exportExpressions']); + expect(annotation.module).toEqual(AnnotatedTemplate.module); + expect(annotation.map).toEqual({ + 'template': '=>template', + 'attr': '@attr', + 'expr': '<=>expr', + 'expr-one-way': '=>exprOneWay', + 'expr-one-way-one-shot': '=>!exprOneWayOneShot', + 'callback': '&callback', + 'expr-one-way2': '=>exprOneWay2', + 'expr-two-way': '<=>exprTwoWay' + }); + }); + describe('exceptions', () { var baseModule; beforeEach(() { @@ -53,7 +76,7 @@ void main() { expect(() { injector.get(DirectiveMap); }).toThrow('Mapping for attribute foo is already defined (while ' - 'processing annottation for field foo of Bad1Component)'); + 'processing annotation for field foo of Bad1Component)'); }); it('should throw when annotated both getter and setter', () { @@ -64,7 +87,7 @@ void main() { expect(() { injector.get(DirectiveMap); }).toThrow('Attribute annotation for foo is defined more than once ' - 'in Bad2Component'); + 'in Bad2Component'); }); }); @@ -112,7 +135,9 @@ class NullParser implements Parser { 'foo': '=>foo' }) class AnnotatedIoComponent { - static module() => new Module()..bind(String, toFactory: (i) => i.get(AnnotatedIoComponent), + static module() => new Module()..bind( + String, + toFactory: (i) => i.get(AnnotatedIoComponent), visibility: Directive.LOCAL_VISIBILITY); AnnotatedIoComponent(Scope scope) { @@ -142,6 +167,43 @@ class AnnotatedIoComponent { set exprTwoWay(val) {} } +@Template( + selector: '[template]', + visibility: Directive.LOCAL_VISIBILITY, + module: AnnotatedTemplate.module, + exportExpressions: const ['exportExpressions'], + map: const {'template': '=>template'}) +class AnnotatedTemplate { + static module() => new Module()..bind( + String, + toFactory: (i) => i.get(AnnotatedTemplate), + visibility: Directive.LOCAL_VISIBILITY); + + var template; + + @NgAttr('attr') + String attr; + + @NgTwoWay('expr') + String expr; + + @NgOneWay('expr-one-way') + String exprOneWay; + + @NgOneWayOneTime('expr-one-way-one-shot') + String exprOneWayOneShot; + + @NgCallback('callback') + Function callback; + + @NgOneWay('expr-one-way2') + set exprOneWay2(val) {} + + @NgTwoWay('expr-two-way') + get exprTwoWay => null; + set exprTwoWay(val) {} +} + @Component( selector: 'bad1', template: r'', @@ -149,6 +211,7 @@ class AnnotatedIoComponent { 'foo': '=>foo' }) class Bad1Component { + // The mapping for foo is already defined in @Component @NgOneWay('foo') String foo; } @@ -157,6 +220,7 @@ class Bad1Component { selector: 'bad2', template: r'') class Bad2Component { + // The mapping for foo is defined on two different attributes @NgOneWay('foo') get foo => null; diff --git a/test/core/registry_spec.dart b/test/core/registry_spec.dart index 1a00d2af0..bd1472131 100644 --- a/test/core/registry_spec.dart +++ b/test/core/registry_spec.dart @@ -53,7 +53,7 @@ class MyMap extends AnnotationMap { class MyAnnotation { final String name; - const MyAnnotation(String this.name); + const MyAnnotation(this.name); toString() => name; get hashCode => name.hashCode; diff --git a/test/core_dom/compiler_spec.dart b/test/core_dom/compiler_spec.dart index 750ed46c5..f1c686333 100644 --- a/test/core_dom/compiler_spec.dart +++ b/test/core_dom/compiler_spec.dart @@ -808,9 +808,9 @@ class LocalAttrDirective { } } -@Decorator( +@Template( selector: '[simple-transclude-in-attach]', - visibility: Directive.CHILDREN_VISIBILITY, children: Directive.TRANSCLUDE_CHILDREN) + visibility: Directive.CHILDREN_VISIBILITY) class SimpleTranscludeInAttachAttrDirective { SimpleTranscludeInAttachAttrDirective(ViewPort viewPort, BoundViewFactory boundViewFactory, Logger log, RootScope scope) { scope.runAsync(() { @@ -844,8 +844,7 @@ class TwoOfTwoDirectives { @Decorator( selector: '[ignore-children]', - children: Directive.IGNORE_CHILDREN -) + compileChildren: false) class IgnoreChildrenDirective { IgnoreChildrenDirective(Logger log) { log('Ignore'); diff --git a/test/core_dom/element_binder_builder_spec.dart b/test/core_dom/element_binder_builder_spec.dart index a7cb0df50..777446033 100644 --- a/test/core_dom/element_binder_builder_spec.dart +++ b/test/core_dom/element_binder_builder_spec.dart @@ -3,14 +3,19 @@ library angular.dom.element_binder_spec; import '../_specs.dart'; import 'dart:mirrors'; -@Component(selector:'component') class _Component{} -@Decorator(selector:'[ignore-children]', - children: Directive.IGNORE_CHILDREN) - class _IgnoreChildren{} -@Decorator(selector:'[structural]', - children: Directive.TRANSCLUDE_CHILDREN) - class _Structural{} -@Decorator(selector:'[directive]') class _DirectiveAttr{} +@Component(selector:'component') +class _Component{} + +@Decorator( + selector:'[ignore-children]', + compileChildren: false) +class _IgnoreChildren{} + +@Template(selector:'[structural]') +class _Structural{} + +@Decorator(selector:'[directive]') +class _DirectiveAttr{} directiveFor(i) { @@ -50,7 +55,7 @@ main() => describe('ElementBinderBuilder', () { expect(b.decorators.length).toEqual(1); expect(b.component).toBeNull(); - expect(b.childMode).toEqual(Directive.COMPILE_CHILDREN); + expect(b.compileChildren).toBe(true); }); @@ -72,6 +77,6 @@ main() => describe('ElementBinderBuilder', () { expect(b.decorators.length).toEqual(1); expect(b.component).toBeNull(); - expect(b.childMode).toEqual(Directive.IGNORE_CHILDREN); + expect(b.compileChildren).toBe(false); }); }); diff --git a/test/core_dom/selector_spec.dart b/test/core_dom/selector_spec.dart index 51c1a6db2..325b176fd 100644 --- a/test/core_dom/selector_spec.dart +++ b/test/core_dom/selector_spec.dart @@ -15,20 +15,17 @@ import '../_specs.dart'; @Component(selector:'component') class _Component{} @Decorator(selector:'[attribute]') class _Attribute{} -@Decorator(selector:'[structural]', - children: Directive.TRANSCLUDE_CHILDREN) - class _Structural{} +@Template(selector:'[structural]') class _Structural{} @Decorator(selector:'[ignore-children]', - children: Directive.IGNORE_CHILDREN) - class _IgnoreChildren{} + compileChildren: false) class _IgnoreChildren{} @Decorator(selector: '[my-model][required]') @Decorator(selector: '[my-model][my-required]') - class _TwoDirectives {} + class _TwoDirectives {} -@Decorator(selector: '[two-directives]') class _OneOfTwoDirectives {} -@Decorator(selector: '[two-directives]') class _TwoOfTwoDirectives {} +@Decorator(selector: '[two-directives]') class _OneOfTwoDirectives {} +@Decorator(selector: '[two-directives]') class _TwoOfTwoDirectives {} main() { diff --git a/test/core_dom/view_spec.dart b/test/core_dom/view_spec.dart index f43ba12ee..eff5debf2 100644 --- a/test/core_dom/view_spec.dart +++ b/test/core_dom/view_spec.dart @@ -9,7 +9,7 @@ class Log { add(String msg) => log.add(msg); } -@Decorator(children: Directive.TRANSCLUDE_CHILDREN, selector: 'foo') +@Template(selector: 'foo') class LoggerViewDirective { LoggerViewDirective(ViewPort port, ViewFactory viewFactory, BoundViewFactory boundViewFactory, Logger logger) { diff --git a/test/directive/ng_if_spec.dart b/test/directive/ng_if_spec.dart index 0f84d59d8..4199ed2e0 100644 --- a/test/directive/ng_if_spec.dart +++ b/test/directive/ng_if_spec.dart @@ -2,9 +2,7 @@ library ng_if_spec; import '../_specs.dart'; -@Decorator( - selector: '[child-controller]', - children: Directive.TRANSCLUDE_CHILDREN) +@Template(selector: '[child-controller]') class ChildController { ChildController(BoundViewFactory boundViewFactory, ViewPort viewPort, diff --git a/test/io/expression_extractor_spec.dart b/test/io/expression_extractor_spec.dart index cf04340a3..4732bafbb 100644 --- a/test/io/expression_extractor_spec.dart +++ b/test/io/expression_extractor_spec.dart @@ -23,8 +23,7 @@ void main() { var sourceCrawler = new SourceCrawlerImpl(['packages/']); var sourceMetadataExtractor = new SourceMetadataExtractor(); List directives = - sourceMetadataExtractor - .gatherDirectiveInfo(file, sourceCrawler); + sourceMetadataExtractor.gatherDirectiveInfo(file, sourceCrawler); var htmlExtractor = new HtmlExpressionExtractor(directives); htmlExtractor.crawl('test/io/test_files/', ioService); diff --git a/test/io/test_files/main.dart b/test/io/test_files/main.dart index cd263cdfd..5aa2c6f55 100644 --- a/test/io/test_files/main.dart +++ b/test/io/test_files/main.dart @@ -2,10 +2,9 @@ library test_files.main; import 'package:angular/core/annotation_src.dart'; -@Decorator( - children: Directive.TRANSCLUDE_CHILDREN, +@Template( selector:'[ng-if]', - map: const {'.': '=>ngIfCondition'}) + map: const {'ng-if': '=>ngIfCondition'}) class NgIfDirective { bool ngIfCondition; } diff --git a/test/io/test_files/routing.dart b/test/io/test_files/routing.dart index 0c7ab6947..3ffe39fe7 100644 --- a/test/io/test_files/routing.dart +++ b/test/io/test_files/routing.dart @@ -4,9 +4,9 @@ import 'package:angular/core/annotation_src.dart'; import 'package:angular/routing/module.dart'; import 'package:di/di.dart'; -@Decorator( +@Template( selector:'[ng-if]', - map: const {'.': '=>ngIfCondition'}) + map: const {'ng-if': '=>ngIfCondition'}) class NgIfDirective { bool ngIfCondition; }