diff --git a/src/ng/directive/attrs.js b/src/ng/directive/attrs.js
index 1b646ff5d4c3..cd0990e60477 100644
--- a/src/ng/directive/attrs.js
+++ b/src/ng/directive/attrs.js
@@ -408,7 +408,7 @@ forEach(ALIASED_ATTR, function(htmlAttr, ngAttr) {
// ng-src, ng-srcset, ng-href are interpolated
forEach(['src', 'srcset', 'href'], function(attrName) {
var normalized = directiveNormalize('ng-' + attrName);
- ngAttributeAliasDirectives[normalized] = function() {
+ ngAttributeAliasDirectives[normalized] = ['$sce', function($sce) {
return {
priority: 99, // it needs to run after the attributes are interpolated
link: function(scope, element, attr) {
@@ -422,6 +422,10 @@ forEach(['src', 'srcset', 'href'], function(attrName) {
propName = null;
}
+ // We need to sanitize the url at least once, in case it is a constant
+ // non-interpolated attribute.
+ attr.$set(normalized, $sce.getTrustedMediaUrl(attr[normalized]));
+
attr.$observe(normalized, function(value) {
if (!value) {
if (attrName === 'href') {
@@ -441,5 +445,5 @@ forEach(['src', 'srcset', 'href'], function(attrName) {
});
}
};
- };
+ }];
});
diff --git a/src/ng/interpolate.js b/src/ng/interpolate.js
index 77b863ddcba9..955b816c202b 100644
--- a/src/ng/interpolate.js
+++ b/src/ng/interpolate.js
@@ -242,7 +242,7 @@ function $InterpolateProvider() {
// Provide a quick exit and simplified result function for text with no interpolation
if (!text.length || text.indexOf(startSymbol) === -1) {
- if (mustHaveExpression && !contextAllowsConcatenation) return;
+ if (mustHaveExpression) return;
var unescapedText = unescapeText(text);
if (contextAllowsConcatenation) {
diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js
index 2dd80560509c..92fc545f3139 100644
--- a/test/ng/compileSpec.js
+++ b/test/ng/compileSpec.js
@@ -3577,6 +3577,15 @@ describe('$compile', function() {
})
);
+ it('should support non-interpolated `src` and `data-src` on the same element',
+ inject(function($rootScope, $compile) {
+ var element = $compile('
')($rootScope);
+ expect(element.attr('src')).toEqual('abc');
+ expect(element.attr('data-src')).toEqual('123');
+ $rootScope.$digest();
+ expect(element.attr('src')).toEqual('abc');
+ expect(element.attr('data-src')).toEqual('123');
+ }));
it('should call observer only when the attribute value changes', function() {
module(function() {
@@ -12084,6 +12093,49 @@ describe('$compile', function() {
expect(element.attr('test6')).toBe('Misko');
}));
+ describe('with media url attributes', function() {
+ it('should work with interpolated ng-attr-src', inject(function() {
+ $rootScope.name = 'some-image.png';
+ element = $compile('
')($rootScope);
+ expect(element.attr('src')).toBeUndefined();
+
+ $rootScope.$digest();
+ expect(element.attr('src')).toBe('some-image.png');
+
+ $rootScope.name = 'other-image.png';
+ $rootScope.$digest();
+ expect(element.attr('src')).toBe('other-image.png');
+ }));
+
+ it('should work with interpolated ng-attr-data-src', inject(function() {
+ $rootScope.name = 'some-image.png';
+ element = $compile('
')($rootScope);
+ expect(element.attr('data-src')).toBeUndefined();
+
+ $rootScope.$digest();
+ expect(element.attr('data-src')).toBe('some-image.png');
+
+ $rootScope.name = 'other-image.png';
+ $rootScope.$digest();
+ expect(element.attr('data-src')).toBe('other-image.png');
+ }));
+
+ it('should work alongside constant [src]-attribute and [ng-attr-data-src] attributes', inject(function() {
+ $rootScope.name = 'some-image.png';
+ element = $compile('
')($rootScope);
+ expect(element.attr('data-src')).toBeUndefined();
+
+ $rootScope.$digest();
+ expect(element.attr('src')).toBe('constant.png');
+ expect(element.attr('data-src')).toBe('some-image.png');
+
+ $rootScope.name = 'other-image.png';
+ $rootScope.$digest();
+ expect(element.attr('src')).toBe('constant.png');
+ expect(element.attr('data-src')).toBe('other-image.png');
+ }));
+ });
+
describe('when an attribute has a dash-separated name', function() {
it('should work with different prefixes', inject(function() {
$rootScope.name = 'JamieMason';
diff --git a/test/ng/directive/ngSrcSpec.js b/test/ng/directive/ngSrcSpec.js
index 5d2a067026b8..fcc48f292afd 100644
--- a/test/ng/directive/ngSrcSpec.js
+++ b/test/ng/directive/ngSrcSpec.js
@@ -78,6 +78,20 @@ describe('ngSrc', function() {
expect(element.prop('src')).toEqual('http://somewhere/abc');
}));
}
+
+ it('should work with `src` attribute on the same element', inject(function($rootScope, $compile) {
+ $rootScope.imageUrl = 'dynamic';
+ element = $compile('
')($rootScope);
+ expect(element.attr('src')).toBe('static');
+ $rootScope.$digest();
+ expect(element.attr('src')).toBe('dynamic');
+ dealoc(element);
+
+ element = $compile('
')($rootScope);
+ expect(element.attr('src')).toBe('static');
+ $rootScope.$digest();
+ expect(element.attr('src')).toBe('dynamic');
+ }));
});
describe('iframe[ng-src]', function() {