2013-04-05 36 views
7

Vấn đề là tôi phải quản lý một danh sách các quả bóng kẹo cao su được lấy từ một dịch vụ. Chỉ thị tôi đã tạo dường như hoạt động khi tôi mã hóa các phần tử trong HTML, nhưng khi tôi cố gắng phân bổ động các quả bóng kẹo cao su bằng cách sử dụng lặp lại ng.AngularJS chỉ thị với ng-repeat không redering

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/

id và màu sắc thuộc tính khi chuyển vào Directi đã kết thúc được không xác định khi được thông qua bằng cách sử dụng ng-lặp lại, nhưng làm việc khi hardcoded trong HTML.

Cảm ơn bạn rất nhiều vì bất kỳ trợ giúp nào bạn có thể cung cấp.

Trả lời

10

Vấn đề ở đây là phạm vi cô lập của bạn. Bằng cách sử dụng scope: {} bạn đã tạo một phạm vi mới, cô lập để hành động trên phần tử đó. Các phạm vi cách ly không kế thừa từ phạm vi gốc. Tất cả các thuộc tính và nội dung trên các chỉ thị với phạm vi cô lập được đánh giá trong bối cảnh của phạm vi cô lập. gumball không tồn tại trong phạm vi cách ly, vì vậy mọi thứ xuất hiện dưới dạng không xác định.

Bạn có hai lựa chọn để sửa lỗi này: (1) xóa phạm vi cách ly (ví dụ: scope: true để tạo phạm vi con); hoặc (2) ràng buộc các giá trị trong phạm vi cô lập của bạn.

Để ràng buộc thuộc tính của bạn để biến phạm vi, bạn chỉ đơn giản là cần phải xác định phạm vi và các loại ràng buộc bạn muốn:

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

này nói rằng các thuộc tính idcolor sẽ được nội suy trong bối cảnh phạm vi cha mẹ và sau đó được thêm vào phạm vi. Bạn có thể xóa tất cả logic đó bên trong hàm link của bạn - điều này sẽ làm điều đó cho bạn.

Nhưng điều này vẫn để lại vấn đề về nội dung bên trong chỉ thị. Để nội suy rằng trong ngữ cảnh của phạm vi gốc, bạn cần phải chuyển đổi:

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

Việc chuyển đổi có nội dung của phần tử và nội suy tương ứng với con mới của phạm vi gốc, ví dụ: nơi gumball vẫn sẽ được xác định.

Với hai thay đổi này, chỉ thị của bạn sẽ hoạt động như mong muốn.

Nếu bạn đang nhầm lẫn về những phạm vi sử dụng, đây là một câu hỏi SO có thể giúp: When writing a directive, how do I decide if a need no new scope, a new child scope, or a new isolate scope?


Side lưu ý: Mặc dù không có phạm vi cô lập, logic trong chức năng link bạn để xác định giá trị thuộc tính sẽ không hoạt động. Thứ tự thực hiện là phần quan trọng ở đây, đó là khoảng: compiler -> controller -> link -> interpolation. Cho đến khi nội suy được thực hiện, không có giá trị cho các thuộc tính của bạn. Vì vậy, séc của bạn sẽ không hoạt động.

Điều đó nói rằng, bạn có thể thiết lập một số $observe trên các thuộc tính được nội suy; các $observe sẽ luôn luôn cháy lần đầu tiên, ngay cả khi không có giá trị được thông qua. Bạn có thể sử dụng tùy chọn này để đặt mặc định của mình. $observe cũng rất hiệu quả.

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

+1 cho thủ thuật giá trị mặc định quan sát $. –

Các vấn đề liên quan