2013-04-05 9 views
7

Das Problem Redering ist, dass ich eine Liste von Gummikugeln zu verwalten habe, die von einem Dienst abgerufen werden. Die Richtlinie habe ich erstellt scheint zu funktionieren, wenn ich die Elemente in der HTML codieren, aber wenn ich versuche, um dynamisch die Gummikugeln mit einem ng-repeat zuordnen.AngularJS Richtlinie mit ng-Wiederholung nicht

HTML

<div ng-controller="GumballsCtrl"> 

<h1>Working</h1> 
    <ul> 
     <li ng-repeat="gumball in Gumballs"> 
      <div class="gumballColor{{gumball.color}}">{{gumball.color}}</div> 
     </li> 
    </ul> 

<h1>Problem - Expecting the same result at the work version</h1> 

    <ul> 
     <li ng-repeat="gumball in Gumballs"> 
      <mygumball id={{gumball.id}} color="{{gumball.color}}">{{gumball.color}}</mygumball> 
     </li> 
    </ul> 
</div> 

JavaScript

var myApp = angular.module('myApp', []); 

function GumballsCtrl($scope, Gumballs) { 
    $scope.Gumballs = Gumballs; 
} 

myApp.factory('Gumballs', function() { 
    return [{ 
     id: '1', 
     color: 'R' 
    }, { 
     id: '2', 
     color: 'G' 
    }, { 
     id: '3', 
     color: 'B' 
    }, { 
     id: '4', 
     color: 'Y' 
    }, { 
     id: '5', 
     color: 'G' 
    }]; 
}); 

myApp.directive('mygumball', function ($scope) { 
    return { 
     restrict: 'E', 

     scope: {}, 

     link: function (scope, element, attrs) { 
      if (attrs.color !== '' && attrs.color !== undefined) { 
       scope.color = attrs.color; 
      } else { 
       scope.color = 'U'; 
      } 
     }, 

     replace: true, 

     template: "<div class='gumballColor{{color}}'>{{color}}</div>" 
    }; 
}); 

CSS

.gumballColorR { 
    font-size: 12px; 
    text-align: center; 
    padding: 2px; 
    -moz-border-radius: 10px; 
    -webkit-border-radius: 10px; 
    border-radius: 10px; 
    border: solid 1px #CC0000; 
    background-color: #FF0000; 
    width: 15px; 
    height: 15px; 
    margin-left: 5px; 
    margin-top: 5px; 
} 
.gumballColorG { 
    font-size: 12px; 
    text-align: center; 
    padding: 2px; 
    -moz-border-radius: 10px; 
    -webkit-border-radius: 10px; 
    border-radius: 10px; 
    border: solid 1px #00CC00; 
    background-color: #00FF00; 
    width: 15px; 
    height: 15px; 
    margin-left: 5px; 
    margin-top: 5px; 
} 
.gumballColorB { 
    font-size: 12px; 
    text-align: center; 
    padding: 2px; 
    color: #FFFFFF; 
    -moz-border-radius: 10px; 
    -webkit-border-radius: 10px; 
    border-radius: 10px; 
    border: solid 1px #0000CC; 
    background-color: #0000FF; 
    width: 15px; 
    height: 15px; 
    margin-left: 5px; 
    margin-top: 5px; 
} 
.gumballColorY { 
    font-size: 12px; 
    text-align: center; 
    padding: 2px; 
    -moz-border-radius: 10px; 
    -webkit-border-radius: 10px; 
    border-radius: 10px; 
    border: solid 1px #CCCC00; 
    background-color: #FFFF00; 
    width: 15px; 
    height: 15px; 
    margin-left: 5px; 
    margin-top: 5px; 
} 
.gumballColorU { 
    font-size: 12px; 
    text-align: center; 
    padding: 2px; 
    -moz-border-radius: 10px; 
    -webkit-border-radius: 10px; 
    border-radius: 10px; 
    border: solid 1px #CCCCCC; 
    background-color: #DDDDDD; 
    width: 15px; 
    height: 15px; 
    margin-left: 5px; 
    margin-top: 5px; 
} 

http://jsfiddle.net/i3sik/NGB9v/22/

Die ID und Farbe, wenn in den Directi geben Attribute Am Ende wird es undefiniert sein, wenn es mit dem ng-repeat übergeben wird, aber wenn es im HTML-Code fest codiert ist.

Vielen Dank für jede Hilfe, die Sie anbieten können.

Antwort

10

Das Problem hier ist Ihr Isolat Umfang. Mit der Verwendung von scope: {} haben Sie einen neuen, isolierenden Bereich erstellt, der für dieses Element gilt. Isolate-Bereiche erben nicht vom übergeordneten Bereich. Alle Attribute und Inhalte von Direktiven mit isolierbaren Gültigkeitsbereichen werden im Kontext des Gültigkeitsbereichs isolieren ausgewertet. gumball existiert nicht im isolieren Bereich, so dass alles als undefiniert auftaucht.

Sie haben zwei Möglichkeiten, dies zu beheben: (1) Entfernen Sie den Isolat Umfang (zum Beispiel scope: true ein Kind Rahmen zu schaffen); oder (2) binden Sie die Werte in Ihrem Isolationsumfang.

Um Ihre Attribute Umfang Variablen binden Sie einfach den Umfang und die Art von Bindung Sie angeben müssen:

scope: { 
    id: '@', 
    color: '@' 
}, 

Dies sagt, dass die Attribute id und color sind im Rahmen interpoliert werden von der übergeordnete Bereich und dann zum Bereich hinzugefügt. Sie können alle diese Logik innerhalb Ihrer link Funktion entfernen - das wird es für Sie tun.

Aber das läßt immer noch das Problem des Inhalts innerhalb die Richtlinie. Um dies im Rahmen des übergeordneten Bereich interpolieren, müssen Sie Einbindung:

transclude: true, 
template: "<div class='gumballColor{{color}}' ng-transclude></div>" 

Transklusion den Inhalt des Elements nimmt und interpoliert in Bezug auf ein neues Kind des übergeordneten Bereich, z.B. wo wäre noch gumball definiert.

Mit diesen beiden Änderungen, Ihre Richtlinie wird wie gewünscht funktionieren.

Wenn Sie verwirrt sind über den Umfang, hier zu verwenden, ist ein andere Frage SO, die helfen können: When writing a directive, how do I decide if a need no new scope, a new child scope, or a new isolate scope?


Randbemerkung: Auch ohne Isolat Umfang, die Logik in Ihrer link Funktion zu bestimmen Attributwerte würden nicht funktionieren. Reihenfolge der Ausführung ist hier der wichtige Teil, der grob ist: Compiler -> Controller -> Link -> Interpolation. Bis die Interpolation abgeschlossen ist, gibt es keinen Wert für Ihre Attribute. Deine Schecks funktionieren also nicht.

Das gesagt, Sie können ein $observe auf interpolierten Attributen einrichten; Die $observe wird immer das erste Mal ausgelöst, auch wenn kein Wert überschritten wurde. Sie können dies verwenden, um Ihren Standard festzulegen. $observe ist auch sehr effizient.

attrs.$observe('attr1', function(val) { 
    if (!angular.isDefined(val)) { 
    scope.attr1 = 'defaultValue'; 
    } 
}); 
+0

+1 für den $ beobachten Standardwert Trick. –

Verwandte Themen