Using chrome Version "20.0.1132.27 beta" (but also seen on other versions)
For this html (obviously it's simplified from the original):
<html ng-app>
<head>
<script src="http://code.angularjs.org/angular-1.0.0rc12.min.js"></script>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<rect x="{{0}}" y="{{0}}" width="{{100}}" height="{{100}}" fill="red"/>
</svg>
</body>
</html>
it draws the expected rectangle, but when I look in the javascript console I see:
Error: Invalid value for
Error: Invalid value for
Error: Invalid value for
Error: Invalid value for
that apparently come from before the values are evaluated. They seem harmless, but are distracting (the real code generates a couple of thousand such errors, due to ng-repeat -- see http://dave.whipp.name/tutorial/anti-alias.html).
Is there a directive or another Angular technique to get around this error? Ng-cloak isn't sufficient.
Sadly, I've run into this exactly same issue. Presumably Chrome is "evaluating" the SVG before AngularJS has a chance to go in and mess with the DOM? (and rightfully cannot evaluate the string "<[ 100+v.row*100 ]>" down to a number with Angular's help).
I have had the same problem. Finally, I decided to write my own directives:
angular.module('yourmodule.directives', [])
.directive('ngX', function() {
return function(scope, element, attrs) {
scope.$watch(attrs.ngX, function(value) {
element.attr('x', value);
});
};
})
Then, use ng-x
attribute instead of x
:
<circle ng-x="{{ x }}" y="0" r="5"></circle>
Finally got rid of annoying error messages.
That is an excellent solution. I will try it out. However, I wonder if I will have to create a whole bunch of directives for all the attributes that are affected.
Thanks.
Similarly to ngHref and ngSrc you can do
angular.forEach(['x', 'y', 'width', 'height'], function(name) {
var ngName = 'ng' + name[0].toUpperCase() + name.slice(1);
myModule.directive(ngName, function() {
return function(scope, element, attrs) {
attrs.$observe(ngName, function(value) {
attrs.$set(name, value);
})
};
});
});
@mtiller I think so. I had to create a whole bunch of directives for all the attributes as well. But, as @rkirov suggested, you can use a loop to do that.
@rkirov I've never used attrs.$observe and attrs.$set. Are those better than using scope.$watch and element.attr? What are the differences?
Thanks for sharing that snippet, @rkirov, super helpful! Strange problem though: If you use that for "d" attributes as well, and try to set the value to empty string, resulting in elem.setAttribute("d", "")
where elem
is a path
element, Chrome will give Error: Problem parsing d=""
in the error console. But according to http://www.w3.org/TR/SVGTiny12/paths.html#DAttribute d=""
is perfectly valid, and this is the way to disable rendering of the path, which sometimes you need. Anyone have any idea what's going on here? Is this a WebKit bug?
Is this a WebKit bug?
Yes.
It seems #1925 is a duplicate of this issue. I didn't notice this one, sorry.
There is a pending PR (https://github.com/angular/angular.js/pull/2061) that solves it using prefixes on the attributes that need late binding.
Unfortunately, as @skivvies pointed out, the problem about d=""
is a WebKit bug...
Great solution vsirisanthana. I was having the same error "Expected moveto path command ('M' or 'm') angular" when drawing a line for the same reason on the attribute 'd'.
angular.module('yourmodule.directives', [])
.directive('ngD', function () {
return function (scope, element, attrs) {
scope.$watch(attrs.ngD, function (value) {
element.attr('d', value);
});
};
});
Many thanks
Actually, these days (AngularJS 1.5) you prepend your attributes with "ng-attr-", so:
<rect x="{{0}}" y="{{0}}" fill="red"/>
would become:
<rect ng-attr-x="{{0}}" ng-attr-y="{{0}}" fill="red"/>
about the problem
Error: Invalid value for
Error: Invalid value for
you can replace the x1 and y1 byng-attr-x1
& ng-attr-y1
When using ngAttr, the allOrNothing flag of $interpolate is used, so if any expression in the interpolated string results in undefined, the attribute is removed and not added to the element
It's working with replacing d with ng-attr-d
Thanks peterjhart , it worked. I was wondering would it work if I created a link function and then processed the component through $onInit.
Most helpful comment
Actually, these days (AngularJS 1.5) you prepend your attributes with "ng-attr-", so:
would become: