2013-05-01 12 views
10

Ich lerne angularjs und ich versuche ng-repeat verwenden, um eine Svg-Grafik zu erstellen.Verwenden Sie Svg mit angularjs ng-repeat

Ich habe diese 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> 

der 'Bereich' ist nur eine einfache Anordnung, die in der Steuereinheit wie folgt definiert ist:

$scope.range = [100, 200, 300]; 

der von HTML-Code ist; Die Rectures werden auf meiner Seite gerendert.

Allerdings hält Chrome den folgenden Fehler zu werfen:

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 

Es scheint, dass es nicht ganz funktioniert wie das, was ich tue ...

Hat jemand eine Idee, warum ich dies empfangen Error?

Antwort

9

Das Problem ist, Chrome sieht die angulare Interpolation str als ungültigen Wert für diese Attribute (seit mindestens einmal das Element tatsächlich im DOM existiert - obwohl unsichtbar - mit "ungültigen" Werten). Ich habe eine Lösung geschrieben, die mit anderen Angular-Lösungen in Bezug auf die Browser-Handhabung von speziellen Attributen übereinstimmt. Anstelle von x, y, width und height geben Sie ng-x, ng-y, ng-width und ng-an. Die Höhe und die tatsächlichen Attribute werden nach der Interpolation der Werte festgelegt.

Hier ist die Lösung on JSFiddle. Ich werde einen Patch an Angular senden, um zu sehen, ob wir das im Kern erreichen können.

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]; 
} 
+9

Winkel 1.1.4 (oder vielleicht früher) hat eine neue generische Richtlinie zu binden spät https : //github.com/lrlopez/angular.js/commit/638e6fdbd60f606dfbe21303f9c94e6d57f0764a – hooblei

+0

@markus, Ihre beiden Lösungen haben hervorragend funktioniert, ich nehme den Attr-ng-Ansatz wie in der Code-Basis –

+0

Das ist großartig, @markus! –

10

Markus' Kommentar späte Bindung zu verwenden, ist am besten.

Ie. Präfix Ihr Attribut entweder mit 'ng-attr-', 'ng: attr:' oder 'ng_attr_', wie folgt aus:

<rect ng:attr:x="{{i/5}}" ng:attr:y="{{i/5}}" ng:attr:width="{{i/5}}" nng:attr:height="{{i/5}}"></rect> 
+1

Perfect, I hatte die gleichen Probleme bei der Verwendung von ng-repeat es zeigte Fehler bei der Verwendung von x, und y Svg attrs und das löste es. – ericsicons

Verwandte Themen