Skip to content
This repository was archived by the owner on Feb 22, 2018. It is now read-only.
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions lib/core_dom/common.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ List<dom.Node> cloneElements(elements) {
return elements.map((el) => el.clone(true)).toList();
}

void normalizeNgAttributes(dom.Element element) {
Map<String, String> normalizedAttrs = {};
element.attributes.forEach((attrName, value) {
Copy link
Contributor

Choose a reason for hiding this comment

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

.filter().forEach() ?

Copy link
Contributor

Choose a reason for hiding this comment

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

actually .filter().map() should do the trick as addAll() will override existing attributes (no need to remove)

Copy link
Contributor

Choose a reason for hiding this comment

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

I keep forgetting there's no filter() for maps...

if (attrName.startsWith('data-ng-')) {
normalizedAttrs[attrName.replaceFirst('data-', '')] = value;
element.attributes.remove(attrName);
}
});
element.attributes.addAll(normalizedAttrs);
}

typedef ApplyMapping(NodeAttrs attrs, Scope scope, Object dst);

class DirectiveRef {
Expand Down
6 changes: 5 additions & 1 deletion lib/core_dom/directive.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ class NodeAttrs {

Map<String, List<AttributeChanged>> _observers;

NodeAttrs(this.element);
NodeAttrs(this.element) {
if (element != null) {
normalizeNgAttributes(element);
}
}

operator [](String attributeName) =>
element.attributes[attributeName];
Expand Down
3 changes: 3 additions & 0 deletions lib/core_dom/selector.dart
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,9 @@ DirectiveSelector directiveSelectorFactory(DirectiveMap directives) {
element.attributes['type'] = 'text';
}

// Normalize ng-* attributes
normalizeNgAttributes(element);

// Select node
partialSelection = elementSelector.selectNode(directiveRefs,
partialSelection, element, nodeName);
Expand Down
7 changes: 4 additions & 3 deletions test/core_dom/directive_spec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ main() {

beforeEach(inject((TestBed tb) {
_ = tb;
element = _.compile('<div foo="bar" foo-bar="baz" foo-bar-baz="foo"></div>');
element = _.compile('<div foo="bar" foo-bar="baz" foo-bar-baz="foo" data-ng-foo="ngfoo"></div>');
nodeAttrs = new NodeAttrs(element);
}));

it('should transform names to camel case', () {
expect(nodeAttrs['foo']).toEqual('bar');
expect(nodeAttrs['foo-bar']).toEqual('baz');
expect(nodeAttrs['foo-bar-baz']).toEqual('foo');
expect(nodeAttrs['ng-foo']).toEqual('ngfoo');
});

it('should return null for unexistent attributes', () {
Expand All @@ -27,7 +28,7 @@ main() {
it('should provide a forEach function to iterate over attributes', () {
Map<String, String> attrMap = new Map();
nodeAttrs.forEach((k, v) => attrMap[k] = v);
expect(attrMap).toEqual({'foo': 'bar', 'foo-bar': 'baz', 'foo-bar-baz': 'foo'});
expect(attrMap).toEqual({'foo': 'bar', 'foo-bar': 'baz', 'foo-bar-baz': 'foo', 'ng-foo': 'ngfoo'});
});

it('should provide a contains method', () {
Expand All @@ -38,7 +39,7 @@ main() {
});

it('should return the attribute names', () {
expect(nodeAttrs.keys.toList()..sort()).toEqual(['foo', 'foo-bar', 'foo-bar-baz']);
expect(nodeAttrs.keys.toList()..sort()).toEqual(['foo', 'foo-bar', 'foo-bar-baz', 'ng-foo']);
});
});
}
56 changes: 56 additions & 0 deletions test/core_dom/selector_spec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ import '../_specs.dart';
@NgDirective(selector:':contains(/abc/)') class _ContainsAbc{}
@NgDirective(selector:'[*=/xyz/]') class _AttributeContainsXyz{}

@NgDirective(selector:'[ng-directive]') class _NgDirectiveAttr{}
@NgDirective(selector:'[ng-directive=d][foo=f]') class _NgDirectiveFooAttr{}
@NgDirective(selector:'b[ng-directive]') class _NgBElementDirectiveAttr{}
@NgDirective(selector:'[ng-directive=value]') class _NgDirectiveValueAttr{}
@NgDirective(selector:'b[ng-directive=value]') class _NgBElementDirectiveValue{}

@NgComponent(selector:'component') class _Component{}
@NgDirective(selector:'[attribute]') class _Attribute{}
@NgDirective(selector:'[structural]',
Expand Down Expand Up @@ -54,6 +60,11 @@ main() {
..type(_BElementDirectiveValue)
..type(_ContainsAbc)
..type(_AttributeContainsXyz)
..type(_NgDirectiveAttr)
..type(_NgDirectiveFooAttr)
..type(_NgBElementDirectiveAttr)
..type(_NgDirectiveValueAttr)
..type(_NgBElementDirectiveValue)
..type(_Component)
..type(_Attribute)
..type(_Structural)
Expand Down Expand Up @@ -125,6 +136,51 @@ main() {
]));
});


it('should match ng-directive on [attribute] with data- prefix', () {
expect(selector(element = e('<div data-ng-directive=abc></div>')),
toEqualsDirectiveInfos([
{ "selector": '[ng-directive]', "value": 'abc', "element": element,
"name": 'directive' }]));

expect(selector(element = e('<div data-ng-directive></div>')),
toEqualsDirectiveInfos([
{ "selector": '[ng-directive]', "value": '', "element": element,
"name": 'directive' }]));
});


it('should match ng-directive on element[attribute] with data- prefix', () {
expect(selector(element = e('<b data-ng-directive=abc></b>')),
toEqualsDirectiveInfos([
{ "selector": 'b', "value": null, "element": element},
{ "selector": '[ng-directive]', "value": 'abc', "element": element},
{ "selector": 'b[ng-directive]', "value": 'abc', "element": element}
]));
});


it('should match ng-directive on [attribute=value] with data- prefix', () {
expect(selector(element = e('<div data-ng-directive=value></div>')),
toEqualsDirectiveInfos([
{ "selector": '[ng-directive]', "value": 'value', "element": element},
{ "selector": '[ng-directive=value]', "value": 'value', "element": element}
]));
});


it('should match ng-directive on element[attribute=value] with data- prefix', () {
expect(selector(element = e('<b data-ng-directive=value></div>')),
toEqualsDirectiveInfos([
{ "selector": 'b', "value": null, "element": element, "name": null},
{ "selector": '[ng-directive]', "value": 'value', "element": element},
{ "selector": '[ng-directive=value]', "value": 'value', "element": element},
{ "selector": 'b[ng-directive]', "value": 'value', "element": element},
{ "selector": 'b[ng-directive=value]', "value": 'value', "element": element}
]));
});


it('should match attributes', () {
expect(selector(element = e('<div attr="before-xyz-after"></div>')),
toEqualsDirectiveInfos([
Expand Down