angularjs:指令和ng类初始化在ng repeat中

angularjs:指令和ng类初始化在ng repeat中,angularjs,Angularjs,当我将控制器中与DOM相关的代码移动到指令时,出现了ng类初始化问题。 简而言之,以下是一些代码: view.html 所以当我有一个div列表时,当我点击一个div时,除了这个,其他所有的div都会变暗 当$scope.rowClick和$scope.changeOpacity在我的控制器中时,一切正常 当我移动行时,单击并将OPCAITY更改为指令: myBar.js 现在我的view.html是这样的: <div ng-repeat="foo in foos" ng-click="r

当我将控制器中与DOM相关的代码移动到指令时,出现了ng类初始化问题。 简而言之,以下是一些代码:

view.html

所以当我有一个div列表时,当我点击一个div时,除了这个,其他所有的div都会变暗

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

当我移动行时,单击并将OPCAITY更改为指令:

myBar.js

现在我的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类初始化div。我必须在每个div上单击一次来初始化它,使用link函数来监听单击

如何在指令中初始化ng类


Thanx.

问题在于,您仅在单击后才将changeOpacity函数放入范围。在链接函数中执行此操作,如下所示:

link: function (scope, element) {
    scope.changeOpacity = function () {
        ...
        same code from changeOpacity
    }
}
将其设置为指令对象的字段没有任何效果

但是,在我看来,使用model属性来指示元素是否处于活动状态并在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>

问题是,您只是在单击之后才将changeOpacity函数放入范围中。在链接函数中执行此操作,如下所示:

link: function (scope, element) {
    scope.changeOpacity = function () {
        ...
        same code from changeOpacity
    }
}
将其设置为指令对象的字段没有任何效果

但是,在我看来,使用model属性来指示元素是否处于活动状态并在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>
ng repeat为数组中的每个项创建子作用域。这意味着ng repeat中指令的作用域将是子作用域。因此,您可以直接在该子范围上设置属性,并使用ng类、ng显示等

下面是基于ng click处理程序切换状态的指令的基本示例

HTML

下面是另一种将选定项存储在父范围控制器中的方法

 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
      }
    }
  })
ng repeat为数组中的每个项创建子作用域。这意味着ng repeat中指令的作用域将是子作用域。因此,您可以直接在该子范围上设置属性,并使用ng类、ng显示等

下面是基于ng click处理程序切换状态的指令的基本示例

HTML

下面是另一种将选定项存储在父范围控制器中的方法

 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
      }
    }
  })

一定要做这个。尝试和jQuery一切都很容易,但是在angular中,您实际上应该只更改您的模型,并让angular为您更改UI。我对这段代码的一个改进是ng click应该调用作用域上的一个方法,并将foo作为参数传递,这样您就可以使除您单击的foo之外的所有其他foo变暗。一定要这样做。尝试和jQuery一切都很容易,但是在angular中,您实际上应该只更改您的模型,并让angular为您更改UI。我可能提供的代码的一个改进是ng click应该调用作用域上的一个方法,并将foo作为参数传递,以便您可以将除单击的foo之外的所有其他foo变暗;访问$parent几乎总是错误的方法。您给出的第一个例子既干净又简单。@HylianPoffball同意,服务更好。。。放在这里主要是为了理解范围。太多的解释,包括一个服务酒店这篇文章。我想远离孤岛范围,也赞成第一种方法,但我反对第二种方法;访问$parent几乎总是错误的方法。您给出的第一个例子既干净又简单。@HylianPoffball同意,服务更好。。。放在这里主要是为了理解范围。太多的解释,包括一个服务酒店这篇文章。我也想远离孤岛范围
 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
        })
      }
    }
  })
 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
      }
    }
  })