AngularJS指令仅在条件为真时

时间:2013-08-22 13:47:54

标签: angularjs angularjs-directive

我将在ng-repeat项目中使用contextmenu指令。 根据条件是否为真,应该应用该指令。 如何仅在item.hasMenu == true时设置条件然后应用指令?

<ul ng-controller="ListViewCtrl" >
<li contextmenu ng-repeat="item in items">{{item.name}} </li>
</ul>

修改

这似乎对我有用。首先是指令。

app.directive('menu',function(){

    return {
        restrict : 'A',

        link : function(scope,element,attrs){

            if(scope.hasMenu){
                        element.contextmenu({
                                        menu:[
                                        {title:"Remove" , "cmd" : "remove"},
                                        {title:"Add" , "cmd" : "add"},
                                        ],
                                        select:function(event,ui){
                                            //alert("select " + ui.cmd + " on" + ui.target.text());
                                            if (ui.cmd ==='remove'){
                                                alert('Remove selected on ' + scope.item);
                                            }
                                            if (ui.cmd ==='add'){
                                                alert("Add selected");
                                            }
                                        }
                        });
            }

        }
    }
    }
);

然后是html

 <ul ng-controller="ListViewCtrl" >
<li menu  ng-repeat="item in items">{{item.name}} </li>
</ul>

3 个答案:

答案 0 :(得分:6)

您可以使用ng-if吗?

执行此类操作
<ul ng-controller="ListViewCtrl" >
   <li ng-repeat="item in items">
      <span>{{item.name}}</span>
      <div contextmenu ng-if="item.hasMenu"></div>
   </li>
</ul>

Here are the docs for ng-if.

编辑: 如果您正在上课的上下文菜单,您应该能够这样做:

<ul ng-controller="ListViewCtrl" >
   <li ng-class="{'hasmenu': item.hasMenu}" ng-repeat="item in items">{{item.name}} </li>
</ul>

答案 1 :(得分:1)

如果您不想更改DOM结构,我认为这非常棘手。如果您可以将contextmenu指令放在<li>内的子DOM节点上,那将会更容易。

但是,我们假设您不能这样做,我们也假设您没有contextmenu指令,因此您无法根据需要进行更改。

这是一个可能解决你的问题的方法,可能有点hackish(实际上我不知道!)

'use strict';

angular.module('myApp', [])

  .controller('TestController', ['$scope', function($scope) {
    $scope.items = [
        {name:1, hasMenu: true}, 
        {name:2, hasMenu: false }, 
        {name:3, hasMenu: true}
      ];
  }])
  .directive('contextmenu', function(){
    return {
      restrict: 'A',
      link: function(scope, element){
        element.css('color', 'red');
      }
    }
  })
  .directive('applyMenu', ['$compile', function($compile){

    return {
      restrict: 'A',
      link: function(scope, element){
        if (scope.item.hasMenu){
          //add the contextmenu directive to the element
          element.attr('contextmenu', '');
          //we need to remove this attr
          //otherwise we would get into an infinite loop
          element.removeAttr('apply-menu');

          //we also need to remove the ng-repeat to not let the ng-repeat 
          //directive come between us.
          //However as we don't know the side effects of 
          //completely removing it, we add it back after
          //the compile process is done.
          var ngRepeat = element.attr('ng-repeat');
          element.removeAttr('ng-repeat');
          var enhanced = $compile(element[0])(scope);
          element.html(enhanced);
          element.attr('ng-repeat', ngRepeat);
        }
      }
    }
  }]);

我伪造了contextmenu指令,只是将color更改为red,以便我们可以看到它正在发生。

然后我创建了一个apply-menu属性指令。该指令比检查hasMenu属性是否为真,如果是,则挂钩并添加contextmenu指令并执行手动$compile过程。

然而,让我担心这个解决方案的一点是我必须暂时删除ng-repeat指令(以及apply-menu指令)以使$compile进程执行我们希望它采取行动的方式。然后,我们在ng-repeat完成后添加$compile指令。那是因为我们不知道从生成的html中完全删除它的副作用。这可能完全有效,但对我来说感觉有点尴尬。

以下是plunker:http://plnkr.co/edit/KrygjX

答案 2 :(得分:0)

你可以这样做

angularApp.directive('element', function($compile) {
        return {
            restrict: 'E',  
            replace: true,
            transclude: true,
            require: '?ngModel',
            scope: 'isolate',
            link: function($scope, elem, attr, ctrl) {
                $scope.isTrue = function() {
                    return attr.hasMenu;
                };
              if($scope.isTrue())
                //some html for control
                elem.html('').show();
              else
                //some html for control
                elem.html('').show(); 

                $compile(elem.contents())($scope);

            }
        };
    });