angularjs:ng-repeat中的指令和ng-class初始化

时间:2013-12-12 10:05:28

标签: angularjs

当我将我的控制器中但与DOM相关的代码移动到指令时,我遇到了ng-class初始化问题。 简而言之,这里有一些代码:

view.html

<div ng-repeat="foo in foos" ng-click="rowClick($index)>
    <div ng-class="changeOpacity($index)>
        <span>{{foo.title}}</span>
        <span>{{foo.name}}</span>
        <span>{{foo.date}}</span>
        ...
        // some div with hidden content. Show when clicking on the div
    </div>
<div>

controller.js

$scope.rowClick = function (idx) {
    // unfold the clicked div to show content
};
$scope.changeOpacity = function (idx) {
    if (this is the div clicked) {
        return {dark: true};
    } else {
        return {light: true};
}

所以当我有一个div列表时。当我点击一个div时,所有其他div都会变得更暗。除此之外。

$ scope.rowClick和$ scope.changeOpacity在我的控制器中时,一切正常。

当我将rowClick和changeOpcaity移动到指令时:

myBar.js

myApp.directive('myBar', function () {
    ...
    return {
        restrict:'A',
        link: function (scope, element) {
           element.bind('click', function () {
               ...
               same code from rowClick
               ...
               scope.changeOpacity = function () {
                   ...
                   same code from changeOpacity
               }
               scope.$apply();
            }
        }),
        changeOpacity: function () {
            ...
            return {light: true} // for all divs
        }
    }
});

现在我的 view.html 是这样的:

<div ng-repeat="foo in foos" ng-click="rowClick($index) my-bar>
    <div ng-class="changeOpacity($index)>
        <span>{{foo.title}}</span>
        <span>{{foo.name}}</span>
        <span>{{foo.date}}</span>
        ...
        // some div with hidden content. Show when clicking on the div
    </div>
<div>

但现在不再使用ng-class初始化div了。我必须在每个div上单击一次以初始化它,并使用链接功能来监听点击。

如何在指令中初始化ng-class?

感谢名单。

2 个答案:

答案 0 :(得分:3)

问题是,只有在点击后才将changeOpacity功能放在示波器中。在链接功能中执行此操作,如下所示:

link: function (scope, element) {
    scope.changeOpacity = function () {
        ...
        same code from changeOpacity
    }
}

使其成为“指令对象”的字段无效。

但是,在我看来,使用模型属性指示元素是否处于活动状态并在ng-click属性中更改此属性会更优雅。然后,您可以在ng-class指令中引用此属性。

这样的事情:

<div ng-repeat="foo in foos" ng-click="foo.active = true>
    <div ng-class="{light: active, dark: !active }>
        <span>{{foo.title}}</span>
        <span>{{foo.name}}</span>
        <span>{{foo.date}}</span>
        <div ng-show="foo.active">
            // some div with hidden content. Show when clicking on the div
        </div>
</div>

答案 1 :(得分:2)

ng-repeat为数组中的每个项创建子范围。这意味着ng-repeat内指令范围内的范围将是子范围。因此,您可以直接在该子范围上设置属性,并使用ng-classng-show

以下是基于ng-click处理程序

切换状态的指令的基本示例

HTML

<div ng-repeat="foo in foos" ng-click="rowClick($index)"  my-directive parent-array="foos">
    <div ng-class="{activeClass: foo.isActive}" class="item">
        <span>{{foo.name}}</span>
        <div ng-show="foo.isActive">Hidden content {{$index+1}}</div>
    </div>
</div>

指令

 app.directive('myDirective',function(){
    return function(scope,elem,attrs){
      /* ng-repeat adds properties like `$first` , `$last` that can be helpful*/
      /* set default first element active*/
      if(scope.$first){
        scope.foo.isActive=true;
      }
      var parentArray=scope[attrs.parentArray];
      /* update active state across array*/
      scope.rowClick=function(idx){
        angular.forEach(parentArray,function(item, index){
          item.isActive = idx==index
        })
      }
    }
  })

DEMO

这是另一种将currSelected项存储在父作用域(控制器)

中的方法
 app.directive('myDirective',function(){
    return function(scope,elem,attrs){

      /* set default first element active*/
      if(scope.$first){
        scope.foo.isActive=true;
        scope.$parent.currSelected=scope.foo
      }

      /* reset previous activeitem  and make item clicked the active one*/
      scope.rowClick=function(item){
        scope.$parent.currSelected.isActive=false
        scope.$parent.currSelected=item;
        item.isActive=true
      }
    }
  })

DEMO