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

Added publishTypes to @NgComponent/@NgDirective #54

Merged
merged 2 commits into from
Jul 23, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions lib/block.dart
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ class Block implements ElementWrapper {
} else {
nodeModule.type(type, type, visibility: visibility);
}
for (var publishType in ref.directive.$publishTypes) {
nodeModule.factory(publishType,
(Injector injector) => injector.get(type),
visibility: visibility);
}
nodeAttrs[ref.directive.$name] = ref.value;
if (ref.directive.isStructural) {
blockListFactory = (Injector injector) => $blockListFactory([node], ref.blockTypes, injector);
Expand Down
99 changes: 65 additions & 34 deletions lib/directive.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,20 @@ String _COMPONENT = '-component';
String _DIRECTIVE = '-directive';
String _ATTR_DIRECTIVE = '-attr' + _DIRECTIVE;

class NgComponent {
class NgAnnotationBase {
final String visibility;
final List<Type> publishTypes;

const NgAnnotationBase({
this.visibility: NgDirective.LOCAL_VISIBILITY,
this.publishTypes
});
}

class NgComponent extends NgAnnotationBase {
final String template;
final String templateUrl;
final String cssUrl;
final String visibility;
final Map<String, String> map;
final String publishAs;
final bool applyAuthorStyles;
Expand All @@ -18,30 +27,31 @@ class NgComponent {
this.template,
this.templateUrl,
this.cssUrl,
this.visibility: NgDirective.LOCAL_VISIBILITY,
visibility,
this.map,
this.publishAs,
this.applyAuthorStyles,
this.resetStyleInheritance
});
this.resetStyleInheritance,
publishTypes : const <Type>[]
}) : super(visibility: visibility, publishTypes: publishTypes);
}

class NgDirective {
class NgDirective extends NgAnnotationBase {
static const String LOCAL_VISIBILITY = 'local';
static const String CHILDREN_VISIBILITY = 'children';
static const String DIRECT_CHILDREN_VISIBILITY = 'direct_children';

final String selector;
final String transclude;
final int priority;
final String visibility;

const NgDirective({
this.selector,
this.transclude,
this.priority : 0,
this.visibility: LOCAL_VISIBILITY
});
visibility,
publishTypes : const <Type>[]
}) : super(visibility: visibility, publishTypes: publishTypes);
}

/**
Expand All @@ -55,6 +65,8 @@ class NgShadowRootOptions {
this.resetStyleInheritance = false]);
}

Map<Type, Directive> _directiveCache = new Map<Type, Directive>();

// TODO(pavelgj): Get rid of Directive and use NgComponent/NgDirective directly.
class Directive {
Type type;
Expand All @@ -70,14 +82,23 @@ class Directive {
Map<String, String> $map;
String $visibility;
NgShadowRootOptions $shadowRootOptions = new NgShadowRootOptions();
List<Type> $publishTypes = <Type>[];

bool isComponent = false;
bool isStructural = false;

Directive(this.type) {
Directive._new(Type this.type);

factory Directive(Type type) {
var instance = _directiveCache[type];
if (instance != null) {
return instance;
}

instance = new Directive._new(type);
var name = type.toString();
var isAttr = false;
$name = name.splitMapJoin(
instance.$name = name.splitMapJoin(
new RegExp(r'[A-Z]'),
onMatch: (m) => '-' + m.group(0).toLowerCase())
.substring(1);
Expand All @@ -91,38 +112,48 @@ class Directive {
var selector;
if (directive != null) {
selector = directive.selector;
$transclude = directive.transclude;
$priority = directive.priority;
$visibility = directive.visibility;
instance.$transclude = directive.transclude;
instance.$priority = directive.priority;
instance.$visibility = directive.visibility;
instance.$publishTypes = directive.publishTypes;
}
if (component != null) {
$template = component.template;
$templateUrl = component.templateUrl;
$cssUrl = component.cssUrl;
$visibility = component.visibility;
$map = component.map;
$publishAs = component.publishAs;
$shadowRootOptions = new NgShadowRootOptions(component.applyAuthorStyles,
component.resetStyleInheritance);
instance.$template = component.template;
instance.$templateUrl = component.templateUrl;
instance.$cssUrl = component.cssUrl;
instance.$visibility = component.visibility;
instance.$map = component.map;
instance.$publishAs = component.publishAs;
instance.$shadowRootOptions =
new NgShadowRootOptions(component.applyAuthorStyles,
component.resetStyleInheritance);
instance.$publishTypes = component.publishTypes;
}

if (selector != null) {
$name = selector;
} else if ($name.endsWith(_ATTR_DIRECTIVE)) {
$name = '[${$name.substring(0, $name.length - _ATTR_DIRECTIVE.length)}]';
} else if ($name.endsWith(_DIRECTIVE)) {
$name = $name.substring(0, $name.length - _DIRECTIVE.length);
} else if ($name.endsWith(_COMPONENT)) {
isComponent = true;
$name = $name.substring(0, $name.length - _COMPONENT.length);
instance.$name = selector;
} else if (instance.$name.endsWith(_ATTR_DIRECTIVE)) {
var attrName = instance.$name.
substring(0, instance.$name.length - _ATTR_DIRECTIVE.length);
instance.$name = '[$attrName]';
} else if (instance.$name.endsWith(_DIRECTIVE)) {
instance.$name = instance.$name.
substring(0, instance.$name.length - _DIRECTIVE.length);
} else if (instance.$name.endsWith(_COMPONENT)) {
instance.isComponent = true;
instance.$name = instance.$name.
substring(0, instance.$name.length - _COMPONENT.length);
} else {
throw "Directive name '$name' must end with $_DIRECTIVE, $_ATTR_DIRECTIVE, $_COMPONENT or have a \$selector field.";
throw "Directive name '$name' must end with $_DIRECTIVE, "
"$_ATTR_DIRECTIVE, $_COMPONENT or have a \$selector field.";
}

isStructural = $transclude != null;
if (isComponent && $map == null) {
$map = new Map<String, String>();
instance.isStructural = instance.$transclude != null;
if (instance.isComponent && instance.$map == null) {
instance.$map = new Map<String, String>();
}
_directiveCache[type] = instance;
return instance;
}
}

Expand Down
17 changes: 13 additions & 4 deletions lib/mirrors.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,16 @@ reflectStaticField(Type type, String field) {
}

// TODO(pavelgj): cache.
Iterable reflectMetadata(Type type, Type metadata) =>
fastReflectClass(type).metadata.where(
(InstanceMirror im) => im.reflectee.runtimeType == metadata)
.map((InstanceMirror im) => im.reflectee);
Iterable reflectMetadata(Type type, Type metadata) {
var meta;
try {
meta = fastReflectClass(type).metadata;
} catch(e) {
// TODO(pavelgj): A temporary workaround for http://dartbug.com/11960
if (e.message == 'Function.prototype.toString is not generic') {
meta = [];
}
}
return meta.where((InstanceMirror im) => im.reflectee.runtimeType == metadata)
.map((InstanceMirror im) => im.reflectee);
}
19 changes: 19 additions & 0 deletions test/compiler_spec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,17 @@ class IncludeTranscludeAttrDirective {
}
}

class PublishTypesDirectiveSuperType {
}

@NgDirective(publishTypes: const [PublishTypesDirectiveSuperType])
class PublishTypesAttrDirective implements PublishTypesDirectiveSuperType {
static Injector _injector;
PublishTypesAttrDirective(Injector injector) {
_injector = injector;
}
}

main() {

describe('dte.compiler', () {
Expand All @@ -65,6 +76,7 @@ main() {
beforeEach(module((AngularModule module) {
module
..directive(TabComponent)
..directive(PublishTypesAttrDirective)
..directive(PaneComponent)
..directive(SimpleTranscludeInAttachAttrDirective)
..directive(IncludeTranscludeAttrDirective)
Expand Down Expand Up @@ -487,6 +499,13 @@ main() {
nextTurn();
expect(element.textWithShadow()).toEqual('WORKED');
})));

it('should "publish" controller to injector under provided publishTypes', inject(() {
var element = $(r'<div publish-types></div>');
$compile(element)(injector, element);
expect(PublishTypesAttrDirective._injector.get(PublishTypesAttrDirective)).
toBe(PublishTypesAttrDirective._injector.get(PublishTypesDirectiveSuperType));
}));
});

describe('controller scoping', () {
Expand Down