Skip to content
This repository has been archived by the owner on Feb 22, 2018. It is now read-only.

Allow specifying a module to use with NgDirective #779

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
42 changes: 31 additions & 11 deletions lib/core/directive.dart
Expand Up @@ -56,7 +56,27 @@ abstract class NgAnnotation {
* direct children of the current DOM element.
*/
final String visibility;
final List<Type> publishTypes;

/**
* A directive/component class can publish types by using a function which
* creates a module. The types specified in module will then be available
* using directive's/component's injector.
*
* Example:
*
* @NgDirective(selector: '[foo]', module: FooDirective.initModule)
* FooDirective {
* static initModule() => new Module()..type(SomeTypeA);
* }
*
* When specifying types, factories or values in the module, notice that
* `Visibility` function maps to `visibility` parameter in [NgDirective] as
* follows:
* * [NgDirective.LOCAL_VISIBILITY] -> [ElementBinder.localVisibility]
* * [NgDirective.CHILDREN_VISIBILITY] -> `null`
* * [NgDirective.DIRECT_CHILDREN_VISIBILITY] -> [ElementBinder.directChildrenVisibility]
*/
final Function module;

/**
* Use map to define the mapping of DOM attributes to fields.
Expand Down Expand Up @@ -139,7 +159,7 @@ abstract class NgAnnotation {
this.selector,
this.children: NgAnnotation.COMPILE_CHILDREN,
this.visibility: NgDirective.LOCAL_VISIBILITY,
this.publishTypes: const [],
this.module,
this.map: const {},
this.exportExpressions: const [],
this.exportExpressionAttrs: const []
Expand Down Expand Up @@ -213,18 +233,18 @@ class NgComponent extends NgAnnotation {
this.applyAuthorStyles,
this.resetStyleInheritance,
this.publishAs,
module,
map,
selector,
visibility,
publishTypes : const <Type>[],
exportExpressions,
exportExpressionAttrs})
: _cssUrls = cssUrl,
super(selector: selector,
children: NgAnnotation.COMPILE_CHILDREN,
visibility: visibility,
publishTypes: publishTypes,
map: map,
module: module,
exportExpressions: exportExpressions,
exportExpressionAttrs: exportExpressionAttrs);

Expand All @@ -241,9 +261,9 @@ class NgComponent extends NgAnnotation {
resetStyleInheritance: resetStyleInheritance,
publishAs: publishAs,
map: newMap,
module: module,
selector: selector,
visibility: visibility,
publishTypes: publishTypes,
exportExpressions: exportExpressions,
exportExpressionAttrs: exportExpressionAttrs);
}
Expand Down Expand Up @@ -271,25 +291,25 @@ class NgDirective extends NgAnnotation {
const NgDirective({children: NgAnnotation.COMPILE_CHILDREN,
map,
selector,
module,
visibility,
publishTypes : const <Type>[],
exportExpressions,
exportExpressionAttrs})
: super(selector: selector,
children: children,
visibility: visibility,
publishTypes: publishTypes,
map: map,
module: module,
exportExpressions: exportExpressions,
exportExpressionAttrs: exportExpressionAttrs);

NgAnnotation cloneWithNewMap(newMap) =>
new NgDirective(
children: children,
map: newMap,
module: module,
selector: selector,
visibility: visibility,
publishTypes: publishTypes,
exportExpressions: exportExpressions,
exportExpressionAttrs: exportExpressionAttrs);
}
Expand Down Expand Up @@ -327,28 +347,28 @@ class NgController extends NgDirective {
children: NgAnnotation.COMPILE_CHILDREN,
this.publishAs,
map,
module,
selector,
visibility,
publishTypes : const <Type>[],
exportExpressions,
exportExpressionAttrs
})
: super(selector: selector,
children: children,
visibility: visibility,
publishTypes: publishTypes,
map: map,
module: module,
exportExpressions: exportExpressions,
exportExpressionAttrs: exportExpressionAttrs);

NgAnnotation cloneWithNewMap(newMap) =>
new NgController(
children: children,
publishAs: publishAs,
module: module,
map: newMap,
selector: selector,
visibility: visibility,
publishTypes: publishTypes,
exportExpressions: exportExpressions,
exportExpressionAttrs: exportExpressionAttrs);
}
Expand Down
16 changes: 8 additions & 8 deletions lib/core_dom/element_binder.dart
Expand Up @@ -78,16 +78,16 @@ class ElementBinder {
_usableDirectiveRefs.isNotEmpty || onEvents.isNotEmpty;

// DI visibility strategy allowing node-local visibility.
static final Function _elementOnly = (Injector requesting, Injector defining) {
static final Function localVisibility = (Injector requesting, Injector defining) {
if (requesting.name == _SHADOW) requesting = requesting.parent;
return identical(requesting, defining);
};

// DI visibility strategy allowing visibility from direct child into parent.
static final Function _elementDirectChildren =
static final Function directChildrenVisibility =
(Injector requesting, Injector defining) {
if (requesting.name == _SHADOW) requesting = requesting.parent;
return _elementOnly(requesting, defining) ||
return localVisibility(requesting, defining) ||
identical(requesting.parent, defining);
};

Expand Down Expand Up @@ -117,7 +117,7 @@ class ElementBinder {

directiveRefs.forEach((DirectiveRef ref) {
NgAnnotation annotation = ref.annotation;
var visibility = _elementOnly;
var visibility = localVisibility;
if (ref.annotation is NgController) {
scope = scope.createChild(new PrototypeMap(scope.context));
nodeModule.value(Scope, scope);
Expand All @@ -128,7 +128,7 @@ class ElementBinder {
visibility = null;
break;
case NgDirective.DIRECT_CHILDREN_VISIBILITY:
visibility = _elementDirectChildren;
visibility = directChildrenVisibility;
break;
}

Expand Down Expand Up @@ -173,9 +173,9 @@ class ElementBinder {
} else {
nodeModule.type(ref.type, visibility: visibility);
}
for (var publishType in ref.annotation.publishTypes) {
nodeModule.factory(publishType, (Injector injector) =>
injector.get(ref.type), visibility: visibility);

if (ref.annotation.module != null) {
nodeModule.install(ref.annotation.module());
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Installs module as a child module. @mhevery What do we do with the visibility? For now I've specified visibility in the injected module itself (see below ng_form.dart:27) but that looks ugly.

}
if (annotation.children == NgAnnotation.TRANSCLUDE_CHILDREN) {
// Currently, transclude is only supported for NgDirective.
Expand Down
10 changes: 6 additions & 4 deletions lib/directive/ng_form.dart
Expand Up @@ -7,22 +7,24 @@ part of angular.directive;
*/
@NgDirective(
selector: 'form',
publishTypes : const <Type>[NgControl],
module: NgForm.initModule,
visibility: NgDirective.CHILDREN_VISIBILITY)
@NgDirective(
selector: 'fieldset',
publishTypes : const <Type>[NgControl],
module: NgForm.initModule,
visibility: NgDirective.CHILDREN_VISIBILITY)
@NgDirective(
selector: '.ng-form',
publishTypes : const <Type>[NgControl],
module: NgForm.initModule,
visibility: NgDirective.CHILDREN_VISIBILITY)
@NgDirective(
selector: '[ng-form]',
publishTypes : const <Type>[NgControl],
module: NgForm.initModule,
map: const { 'ng-form': '@name' },
visibility: NgDirective.CHILDREN_VISIBILITY)
class NgForm extends NgControl {
static initModule() => new Module()..factory(NgControl, (i) => i.get(NgForm));

final Scope _scope;

/**
Expand Down
5 changes: 4 additions & 1 deletion lib/routing/ng_bind_route.dart
Expand Up @@ -24,14 +24,17 @@ part of angular.routing;
*/
@NgDirective(
visibility: NgDirective.CHILDREN_VISIBILITY,
publishTypes: const [RouteProvider],
selector: '[ng-bind-route]',
module: NgBindRouteDirective.initModule,
map: const {'ng-bind-route': '@routeName'})
class NgBindRouteDirective implements RouteProvider {
Router _router;
String routeName;
Injector _injector;

static initModule() => new Module()..factory(RouteProvider,
(i) => i.get(NgBindRouteDirective));

// We inject NgRoutingHelper to force initialization of routing.
NgBindRouteDirective(this._router, this._injector, NgRoutingHelper _);

Expand Down
5 changes: 4 additions & 1 deletion lib/routing/ng_view.dart
Expand Up @@ -57,9 +57,12 @@ part of angular.routing;
*/
@NgDirective(
selector: 'ng-view',
publishTypes: const [RouteProvider],
module: NgViewDirective.initModule,
visibility: NgDirective.CHILDREN_VISIBILITY)
class NgViewDirective implements NgDetachAware, RouteProvider {
static initModule() =>
new Module()..factory(RouteProvider, (i) => i.get(RouteProvider));

final NgRoutingHelper locationService;
final ViewCache viewCache;
final Injector injector;
Expand Down
8 changes: 6 additions & 2 deletions test/core/core_directive_spec.dart
Expand Up @@ -19,7 +19,7 @@ void main() {
expect(annotation.selector).toEqual('annotated-io');
expect(annotation.visibility).toEqual(NgDirective.LOCAL_VISIBILITY);
expect(annotation.exportExpressions).toEqual(['exportExpressions']);
expect(annotation.publishTypes).toEqual([String]);
expect(annotation.module).toEqual(AnnotatedIoComponent.initModule);
expect(annotation.template).toEqual('template');
expect(annotation.templateUrl).toEqual('templateUrl');
expect(annotation.cssUrls).toEqual(['cssUrls']);
Expand Down Expand Up @@ -86,13 +86,17 @@ class NullParser implements Parser {
applyAuthorStyles: true,
resetStyleInheritance: true,
publishAs: 'ctrl',
publishTypes: const [String],
module: AnnotatedIoComponent.initModule,
visibility: NgDirective.LOCAL_VISIBILITY,
exportExpressions: const ['exportExpressions'],
map: const {
'foo': '=>foo'
})
class AnnotatedIoComponent {
static initModule() => new Module()..factory(String,
(i) => i.get(AnnotatedIoComponent),
visibility: ElementBinder.localVisibility);

AnnotatedIoComponent(Scope scope) {
scope.rootScope.context['ioComponent'] = this;
}
Expand Down
3 changes: 2 additions & 1 deletion test/core_dom/compiler_spec.dart
Expand Up @@ -727,9 +727,10 @@ class PublishTypesDirectiveSuperType {

@NgDirective(
selector: '[publish-types]',
publishTypes: const [PublishTypesDirectiveSuperType])
module: PublishTypesAttrDirective.initModule)
class PublishTypesAttrDirective implements PublishTypesDirectiveSuperType {
static Injector _injector;
static initModule() => new Module()..factory(PublishTypesDirectiveSuperType, (injector) => injector.get(PublishTypesAttrDirective));
PublishTypesAttrDirective(Injector injector) {
_injector = injector;
}
Expand Down