undefined - AngularJS directive with ng-repeat not redering -


the problem have manage list of gum balls retrieved service. directive i've created seems work when hardcode elements in html, when attempt dynamically allocate gum balls using ng-repeat.

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 same result @ 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/

the id , color attributes when passed directive end being undefined when passed using ng-repeat, work when hardcoded in html.

thank can provide.

the problem here isolate scope. using scope: {} created new, isolate scope act on element. isolate scopes don't inherit parent scope. attributes , content on directives isolate scopes evaluated within context of isolate scope. gumball doesn't exist in isolate scope, comes undefined.

you have 2 choices fix this: (1) remove isolate scope (e.g. scope: true create child scope); or (2) bind values in isolate scope.

to bind attributes scope variables, need specify scope , kind of binding want:

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

this says attributes id , color interpolated in context of parent scope , added scope. can remove logic inside link function - you.

but still leaves problem of content inside directive. interpolate in context of parent scope, need transclusion:

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

transclusion takes contents of element , interpolates relative new child of parent scope, e.g. gumball still defined.

with these 2 changes, directive work desired.

if you're confused scope use, here's question might help: when writing directive, how decide if need no new scope, new child scope, or new isolate scope?


side note: without isolate scope, logic in link function determine attribute values wouldn't work. order of execution important part here, roughly: compiler -> controller -> link -> interpolation. until interpolation done, there no value attributes. checks won't work.

that said, can set $observe on interpolated attributes; $observe fire first time, if there no value passed. can use set default. $observe efficient.

attrs.$observe( 'attr1', function(val) {   if ( !angular.isdefined( val ) ) {     scope.attr1 = 'defaultvalue';   } }); 

Comments

Popular posts from this blog

asp.net mvc 3 - Using mvc3, I need to add a username/password to the sql connection string at runtime -

kineticjs - draw multiple lines and delete individual line -

thumbnails - jQuery image rotate on hover -