Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit d8e3707

Browse files
Wesley Chopetebacondarwin
Wesley Cho
authored andcommitted
feat($compile): add support for ng-attr with camelCased attributes
SVG attributes are case sensitive and some have upper case letters in them This change ensures that we can identify these, when being used with the `ng-attr` directive, by encoding upper case letters with a preceding underscore. For example to apply `ng-attr` to the `viewBox` attribute we could write `ng-attr-view_box` - or any of the other variants: `ng:attr:view_box`, `data-ng-attr-view_box`, etc. Closes #9845 Closes #10194
1 parent ca4df47 commit d8e3707

File tree

3 files changed

+49
-3
lines changed

3 files changed

+49
-3
lines changed

docs/content/guide/directive.ngdoc

+9
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,15 @@ For example, we could fix the example above by instead writing:
174174
</svg>
175175
```
176176

177+
If one wants to modify a camelcased attribute (SVG elements have valid camelcased attributes), such as `viewBox` on the `svg` element, one can use underscores to denote that the attribute to bind to is naturally camelcased.
178+
179+
For example, to bind to `viewBox`, we can write:
180+
181+
```html
182+
<svg ng-attr-view_box="{{viewBox}}">
183+
</svg>
184+
```
185+
177186

178187
## Creating Directives
179188

src/ng/compile.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -1420,7 +1420,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
14201420
// support ngAttr attribute binding
14211421
ngAttrName = directiveNormalize(name);
14221422
if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) {
1423-
name = snake_case(ngAttrName.substr(6), '-');
1423+
name = name.replace(PREFIX_REGEXP, '')
1424+
.substr(8).replace(/_(.)/g, function(match, letter) {
1425+
return letter.toUpperCase();
1426+
});
14241427
}
14251428

14261429
var directiveNName = ngAttrName.replace(/(Start|End)$/, '');

test/ng/compileSpec.js

+36-2
Original file line numberDiff line numberDiff line change
@@ -6542,16 +6542,21 @@ describe('$compile', function() {
65426542
expect(element.attr('href')).toBe('test/test');
65436543
}));
65446544

6545-
it('should work if they are prefixed with x- or data-', inject(function($compile, $rootScope) {
6545+
it('should work if they are prefixed with x- or data- and different prefixes', inject(function($compile, $rootScope) {
65466546
$rootScope.name = "Misko";
6547-
element = $compile('<span data-ng-attr-test2="{{name}}" x-ng-attr-test3="{{name}}" data-ng:attr-test4="{{name}}"></span>')($rootScope);
6547+
element = $compile('<span data-ng-attr-test2="{{name}}" x-ng-attr-test3="{{name}}" data-ng:attr-test4="{{name}}" ' +
6548+
'x_ng-attr-test5="{{name}}" data:ng-attr-test6="{{name}}"></span>')($rootScope);
65486549
expect(element.attr('test2')).toBeUndefined();
65496550
expect(element.attr('test3')).toBeUndefined();
65506551
expect(element.attr('test4')).toBeUndefined();
6552+
expect(element.attr('test5')).toBeUndefined();
6553+
expect(element.attr('test6')).toBeUndefined();
65516554
$rootScope.$digest();
65526555
expect(element.attr('test2')).toBe('Misko');
65536556
expect(element.attr('test3')).toBe('Misko');
65546557
expect(element.attr('test4')).toBe('Misko');
6558+
expect(element.attr('test5')).toBe('Misko');
6559+
expect(element.attr('test6')).toBe('Misko');
65556560
}));
65566561

65576562
describe('when an attribute has a dash-separated name', function() {
@@ -6619,6 +6624,35 @@ describe('$compile', function() {
66196624
});
66206625

66216626

6627+
describe('when an attribute has an underscore-separated name', function() {
6628+
6629+
it('should work with different prefixes', inject(function($compile, $rootScope) {
6630+
$rootScope.dimensions = "0 0 0 0";
6631+
element = $compile('<svg ng:attr:view_box="{{dimensions}}"></svg>')($rootScope);
6632+
expect(element.attr('viewBox')).toBeUndefined();
6633+
$rootScope.$digest();
6634+
expect(element.attr('viewBox')).toBe('0 0 0 0');
6635+
}));
6636+
6637+
it('should work if they are prefixed with x- or data-', inject(function($compile, $rootScope) {
6638+
$rootScope.dimensions = "0 0 0 0";
6639+
$rootScope.number = 0.42;
6640+
$rootScope.scale = 1;
6641+
element = $compile('<svg data-ng-attr-view_box="{{dimensions}}">' +
6642+
'<filter x-ng-attr-filter_units="{{number}}">' +
6643+
'<feDiffuseLighting data-ng:attr_surface_scale="{{scale}}">' +
6644+
'</feDiffuseLighting>' +
6645+
'<feSpecularLighting x-ng:attr_surface_scale="{{scale}}">' +
6646+
'</feSpecularLighting></filter></svg>')($rootScope);
6647+
expect(element.attr('viewBox')).toBeUndefined();
6648+
$rootScope.$digest();
6649+
expect(element.attr('viewBox')).toBe('0 0 0 0');
6650+
expect(element.find('filter').attr('filterUnits')).toBe('0.42');
6651+
expect(element.find('feDiffuseLighting').attr('surfaceScale')).toBe('1');
6652+
expect(element.find('feSpecularLighting').attr('surfaceScale')).toBe('1');
6653+
}));
6654+
});
6655+
66226656
describe('multi-element directive', function() {
66236657
it('should group on link function', inject(function($compile, $rootScope) {
66246658
$rootScope.show = false;

0 commit comments

Comments
 (0)