Reputation: 40860
My angular page which I reduced to a to a minimal example here I tried three different ways to show the same img (just a red rectangle) in the "img"-Page:
In Firefox all three images are displayed just fine.
In Opera the page shows only the later two images.
Chromium refuses to even load the page at all (it says "Error: An invalid or illegal string was specified." on the console). (It works if I remove the XML-Style img).
Why is this happening? Since I believe in XML my preference would be to get the XML-Style Parameter to work in all browsers. Note that I don't care about Internet Explorer.
Archive with my (broken) project: http://cipher-code.de/tmp/angular.zip
Upvotes: 2
Views: 1112
Reputation: 27062
Chrome appears to be quite strict when injecting fragments of XML into an XML document, with regards to namespaces. Your partial of images
<section>
<h1>Img</h1>
<p>With ng:src: <img ng:src="{{img}}" /></p>
<p>With ng-src: <img ng-src="{{img}}" /></p>
<p>With src: <img src="{{img}}" /></p>
<p>As link: <a href="{{img}}">Go to img</a></p>
</section>
is using the ng
namespace, but it's not declared. The following fixes it in Chrome
<section xmlns:ng="http://angularjs.org">
<h1>Img</h1>
<p>With ng:src: <img ng:src="{{img}}" /></p>
<p>With ng-src: <img ng-src="{{img}}" /></p>
<p>With src: <img src="{{img}}" /></p>
<p>As link: <a href="{{img}}">Go to img</a></p>
</section>
Alas not sure why it then doesn't work in Opera.
Edit:
After a bit more testing, it looks like Opera can't quite cope with attributes src
and ng:src
on the same element. A solution is to roll your own ngSrc
directive, called something like myImgsrc
,
myModule.directive('myImgsrc', function() {
return {
link: function(scope, element, attrs) {
attrs.$observe('myImgsrc', function(src) {
attrs.$set('src', src);
});
}
}
});
Used as:
<img my:imgsrc="{{img}}" />
(Remembering to properly declare the namespace xmlns:my="http://mydomain.com"
in both the document and the partial, so as not to break Chrome)
Upvotes: 1
Reputation: 9457
The XHTML spec outlines this algorithm that Chrome does not implement fully. Chrome returns the error you observe when the XML is not well formed, which is true when the following step in the algorithm is not followed:
If there is a context element, feed the parser just created the string corresponding to the start tag of that element, declaring all the namespace prefixes that are in scope on that element in the DOM, as well as declaring the default namespace (if any) that is in scope on that element in the DOM.
The result of not following this step means you have to set xmlns:ng
on the root element of the fragment you are appending (or technically, any element or parent thereof that uses the ng
namespace)
Edit after further discussion in comments: element.setAttribute
on Opera doesn't do anything if the attribute doesn't exist. AngularJS has a compatibility fix for this for Internet Explorer. Enabling this fix for Opera solves the issue on Opera as well. A bug is issued with AngularJS here. Internet Explorer and Opera seem to misinterpret the spec on this.
Upvotes: 4