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

Commit a1e7eb6

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 169e532 commit a1e7eb6

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
@@ -172,6 +172,15 @@ For example, we could fix the example above by instead writing:
172172
</svg>
173173
```
174174

175+
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.
176+
177+
For example, to bind to `viewBox`, we can write:
178+
179+
```html
180+
<svg ng-attr-view_box="{{viewBox}}">
181+
</svg>
182+
```
183+
175184

176185
## Creating Directives
177186

src/ng/compile.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -1051,7 +1051,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
10511051
// support ngAttr attribute binding
10521052
ngAttrName = directiveNormalize(name);
10531053
if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) {
1054-
name = snake_case(ngAttrName.substr(6), '-');
1054+
name = name.replace(PREFIX_REGEXP, '')
1055+
.substr(8).replace(/_(.)/g, function(match, letter) {
1056+
return letter.toUpperCase();
1057+
});
10551058
}
10561059

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

test/ng/compileSpec.js

+36-2
Original file line numberDiff line numberDiff line change
@@ -5040,16 +5040,21 @@ describe('$compile', function() {
50405040
expect(element.attr('href')).toBe('test/test');
50415041
}));
50425042

5043-
it('should work if they are prefixed with x- or data-', inject(function($compile, $rootScope) {
5043+
it('should work if they are prefixed with x- or data- and different prefixes', inject(function($compile, $rootScope) {
50445044
$rootScope.name = "Misko";
5045-
element = $compile('<span data-ng-attr-test2="{{name}}" x-ng-attr-test3="{{name}}" data-ng:attr-test4="{{name}}"></span>')($rootScope);
5045+
element = $compile('<span data-ng-attr-test2="{{name}}" x-ng-attr-test3="{{name}}" data-ng:attr-test4="{{name}}" ' +
5046+
'x_ng-attr-test5="{{name}}" data:ng-attr-test6="{{name}}"></span>')($rootScope);
50465047
expect(element.attr('test2')).toBeUndefined();
50475048
expect(element.attr('test3')).toBeUndefined();
50485049
expect(element.attr('test4')).toBeUndefined();
5050+
expect(element.attr('test5')).toBeUndefined();
5051+
expect(element.attr('test6')).toBeUndefined();
50495052
$rootScope.$digest();
50505053
expect(element.attr('test2')).toBe('Misko');
50515054
expect(element.attr('test3')).toBe('Misko');
50525055
expect(element.attr('test4')).toBe('Misko');
5056+
expect(element.attr('test5')).toBe('Misko');
5057+
expect(element.attr('test6')).toBe('Misko');
50535058
}));
50545059

50555060
describe('when an attribute has a dash-separated name', function () {
@@ -5083,6 +5088,35 @@ describe('$compile', function() {
50835088
});
50845089

50855090

5091+
describe('when an attribute has an underscore-separated name', function() {
5092+
5093+
it('should work with different prefixes', inject(function($compile, $rootScope) {
5094+
$rootScope.dimensions = "0 0 0 0";
5095+
element = $compile('<svg ng:attr:view_box="{{dimensions}}"></svg>')($rootScope);
5096+
expect(element.attr('viewBox')).toBeUndefined();
5097+
$rootScope.$digest();
5098+
expect(element.attr('viewBox')).toBe('0 0 0 0');
5099+
}));
5100+
5101+
it('should work if they are prefixed with x- or data-', inject(function($compile, $rootScope) {
5102+
$rootScope.dimensions = "0 0 0 0";
5103+
$rootScope.number = 0.42;
5104+
$rootScope.scale = 1;
5105+
element = $compile('<svg data-ng-attr-view_box="{{dimensions}}">' +
5106+
'<filter x-ng-attr-filter_units="{{number}}">' +
5107+
'<feDiffuseLighting data-ng:attr_surface_scale="{{scale}}">' +
5108+
'</feDiffuseLighting>' +
5109+
'<feSpecularLighting x-ng:attr_surface_scale="{{scale}}">' +
5110+
'</feSpecularLighting></filter></svg>')($rootScope);
5111+
expect(element.attr('viewBox')).toBeUndefined();
5112+
$rootScope.$digest();
5113+
expect(element.attr('viewBox')).toBe('0 0 0 0');
5114+
expect(element.find('filter').attr('filterUnits')).toBe('0.42');
5115+
expect(element.find('feDiffuseLighting').attr('surfaceScale')).toBe('1');
5116+
expect(element.find('feSpecularLighting').attr('surfaceScale')).toBe('1');
5117+
}));
5118+
});
5119+
50865120
describe('multi-element directive', function() {
50875121
it('should group on link function', inject(function($compile, $rootScope) {
50885122
$rootScope.show = false;

0 commit comments

Comments
 (0)