具有ng-repeat不渲染的AngularJS指令

时间:2013-04-05 06:19:24

标签: angularjs angularjs-ng-repeat undefined directive

问题是我必须管理从服务中检索到的口香糖球列表。当我在HTML中对元素进行硬编码时,我创建的指令似乎有效,但是当我尝试使用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 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和color属性在使用ng-repeat传递时最终未定义,但在HTML中进行硬编码时工作。

1 个答案:

答案 0 :(得分:10)

这里的问题是你的隔离范围。通过使用scope: {},您创建了一个新的隔离范围来对该元素进行操作。隔离范围不从父范围继承。具有隔离范围的指令上的所有属性和内容都在隔离范围的上下文中进行评估。 <{1}}在隔离范围中不存在,因此所有内容都是未定义的。

您有两种方法可以解决此问题:(1)删除隔离范围(例如gumball以创建子范围);或(2)绑定隔离范围内的值。

要将属性绑定到范围变量,只需指定范围和所需的绑定类型:

scope: true

这表示属性scope: { id: '@', color: '@' }, id将在父作用域的上下文中进行插值,然后添加到作用域中。您可以删除color功能中的所有逻辑 - 这将为您完成。

但这仍然留下指令内容的问题。要在父范围的上下文中插入它,您需要进行转义:

link

Transclusion获取元素的内容并相对于父范围的新子元素进行插值,例如其中transclude: true, template: "<div class='gumballColor{{color}}' ng-transclude></div>" 仍将被定义。

通过这两项更改,您的指令将按照需要运行。

如果您对使用哪个范围感到困惑,这是另一个可能有用的SO问题:When writing a directive, how do I decide if a need no new scope, a new child scope, or a new isolate scope?


旁注:即使没有隔离范围,gumball函数中用于确定属性值的逻辑也不起作用。执行顺序是这里的重要部分,大致是:编译器 - &gt;控制器 - &gt;链接 - &gt;插值。在插值完成之前,您的属性没有任何值。所以你的检查不起作用。

也就是说,您可以在插值属性上设置link; $observe将始终在第一次触发,即使没有传递值。您可以使用它来设置默认值。 $observe也非常有效。

$observe