Skip to content

Commit 72b9104

Browse files
committed
fix(ngSrc, ngSrcset, ngHref): only interpolate if all expressions are defined
BREAKING CHANGE If `bar` is `undefined`, before `<img src="foo/{{bar}}.jpg">` yields `<img src="foo/.jpg">`. With this change, the binding will not set `src`. If you want the old behavior, you can do this: `<img src="foo/{{bar || ''}}.jpg">`. The same applies for `srcset` and `href`. Closes angular#6984
1 parent fcc3a7a commit 72b9104

File tree

3 files changed

+20
-10
lines changed

3 files changed

+20
-10
lines changed

src/ng/directive/booleanAttrs.js

+16-6
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ forEach(BOOLEAN_ATTR, function(propName, attrName) {
365365
// ng-src, ng-srcset, ng-href are interpolated
366366
forEach(['src', 'srcset', 'href'], function(attrName) {
367367
var normalized = directiveNormalize('ng-' + attrName);
368-
ngAttributeAliasDirectives[normalized] = function() {
368+
ngAttributeAliasDirectives[normalized] = ['$interpolate', '$sce', function($interpolate, $sce) {
369369
return {
370370
priority: 99, // it needs to run after the attributes are interpolated
371371
link: function(scope, element, attr) {
@@ -379,11 +379,21 @@ forEach(['src', 'srcset', 'href'], function(attrName) {
379379
propName = null;
380380
}
381381

382-
attr.$observe(normalized, function(value) {
383-
if (!value)
384-
return;
382+
var parsed = $interpolate(element.attr(attr.$attr[normalized]));
383+
384+
scope.$watchGroup(parsed.expressions, function (values) {
385+
var merged = '';
386+
for (var i = values.length - 1; i >= 0; i -= 1) {
387+
if (isDefined(values[i])) {
388+
merged += parsed.separators[i] + values[i];
389+
} else {
390+
return;
391+
}
392+
}
385393

386-
attr.$set(name, value);
394+
merged += parsed.separators[values.length];
395+
396+
attr.$set(name, merged);
387397

388398
// on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist
389399
// then calling element.setAttribute('src', 'foo') doesn't do anything, so we need
@@ -393,5 +403,5 @@ forEach(['src', 'srcset', 'href'], function(attrName) {
393403
});
394404
}
395405
};
396-
};
406+
}];
397407
});

test/ng/directive/booleanAttrsSpec.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ describe('ngSrcset', function() {
204204
var element = $compile('<div ng-srcset="some/{{id}} 2x"></div>')($rootScope);
205205

206206
$rootScope.$digest();
207-
expect(element.attr('srcset')).toEqual('some/ 2x');
207+
expect(element.attr('srcset')).toEqual();
208208

209209
$rootScope.$apply(function() {
210210
$rootScope.id = 1;
@@ -227,7 +227,7 @@ describe('ngHref', function() {
227227
it('should interpolate the expression and bind to href', inject(function($compile, $rootScope) {
228228
element = $compile('<div ng-href="some/{{id}}"></div>')($rootScope);
229229
$rootScope.$digest();
230-
expect(element.attr('href')).toEqual('some/');
230+
expect(element.attr('href')).toEqual();
231231

232232
$rootScope.$apply(function() {
233233
$rootScope.id = 1;
@@ -258,7 +258,7 @@ describe('ngHref', function() {
258258
element = $compile('<svg><a ng-href="some/{{id}}"></a></svg>')($rootScope);
259259
var child = element.children('a');
260260
$rootScope.$digest();
261-
expect(child.attr('xlink:href')).toEqual('some/');
261+
expect(child.attr('xlink:href')).toEqual();
262262

263263
$rootScope.$apply(function() {
264264
$rootScope.id = 1;

test/ng/directive/ngSrcsetSpec.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ describe('ngSrcset', function() {
1111
$rootScope.image = {};
1212
element = $compile('<img ng-srcset="{{image.url}} 2x">')($rootScope);
1313
$rootScope.$digest();
14-
expect(element.attr('srcset')).toEqual(' 2x');
14+
expect(element.attr('srcset')).toEqual();
1515
}));
1616
});

0 commit comments

Comments
 (0)