I am learning angularjs and I am trying use ng-repeat to create an svg graph.
I have this html:
<svg>
<g id="g_{{$index}}" ng-repeat="i in range" ng-cloak>
<rect x="{{i / 5}}" y="{{i / 5}}" width="{{i / 5}}" height="{{i / 5}}"></rect>
</g>
</svg>
the 'range' is just a simple array which is defined in controller like this:
$scope.range = [100, 200, 300];
the html is working; the rects are rendered on my page.
However, Chrome keeps throwing the following error:
Error: Invalid value for <rect> attribute height="{{i / 5}}" js/angular.js:1584
JQLiteClone js/angular.js:1584
JQLite.(anonymous function) js/angular.js:2163
publicLinkFn js/angular.js:3862
ngRepeatWatch js/angular.js:13641
Scope.$digest js/angular.js:7889
Scope.$apply js/angular.js:8097
js/angular.js:961
invoke js/angular.js:2857
resumeBootstrapInternal js/angular.js:959
bootstrap js/angular.js:973
angularInit js/angular.js:934
js/angular.js:14756
fire js/jquery-2.0.0.js:2863
self.fireWith js/jquery-2.0.0.js:2975
jQuery.extend.ready js/jquery-2.0.0.js:398
completed js/jquery-2.0.0.js:93
It seems that it does not quite like what I am doing...
Does anyone have an idea why I'm receiving this error?
The problem is Chrome sees the Angular interpolation str as an invalid value for those attributes (since at least at one time the element actually exists in the DOM -- though invisibly -- with "invalid" values). I have written a solution that is in line with other Angular solutions as to browser handling of special attributes where instead of using x, y, width, and height, you specify ng-x, ng-y, ng-width, and ng-height and the real attributes are set after the values are interpolated.
Here is the solution on JSFiddle. I'm going to submit a patch to Angular to see if we can get this in the core.
HTML
<div ng-app="SampleApp" ng-controller="MainCtrl">
<svg>
<g id="g_{{$index}}" ng-repeat="i in range" ng-cloak>
<rect ng-x="{{i / 5}}" ng-y="{{i / 5}}" ng-width="{{i / 5}}" ng-height="{{i / 5}}"></rect>
</g>
</svg>
</div>
JS
angular.module('SampleApp', [], function() {})
.directive('ngX', function() {
return function(scope, elem, attrs) {
attrs.$observe('ngX', function(x) {
elem.attr('x', x);
});
};
})
.directive('ngY', function() {
return function(scope, elem, attrs) {
attrs.$observe('ngY', function(y) {
elem.attr('y', y);
});
};
})
.directive('ngWidth', function() {
return function(scope, elem, attrs) {
attrs.$observe('ngWidth', function(width) {
elem.attr('width', width);
});
};
})
.directive('ngHeight', function() {
return function(scope, elem, attrs) {
attrs.$observe('ngHeight', function(height) {
elem.attr('height', height);
});
};
});
function MainCtrl($scope) {
$scope.range = [100, 200, 300];
}
Markus' comment to use late binding is best.
Ie. prefix your attribute with either 'ng-attr-', 'ng:attr:' or 'ng_attr_', like this:
<rect ng:attr:x="{{i / 5}}" ng:attr:y="{{i / 5}}" ng:attr:width="{{i / 5}}" nng:attr:height="{{i / 5}}"></rect>
来源:https://stackoverflow.com/questions/16318768/use-svg-with-angularjs-ng-repeat