AngularJS指令在点击时添加类,但如果单击则删除并将其添加到另一个元素

时间:2014-05-27 22:45:50

标签: javascript angularjs angularjs-directive

我有一个简单的指令,用于在点击时添加一个类,如果再次单击,则将其从元素中删除。但是,我想重构它以便在通用菜单中更常用。相反,如果单击的<li>元素不是当前活动元素,则应将其从当前元素中删除并将其放在新元素上。基本上我想添加一个&#34; active&#34;类到当前活动的<li>元素。

在我的菜单中,我有:

<ul>
    <li><a swapit ng-click="lol(stillgot)" class="select-show">Still Got Game</a></li>
    <li><a swapit ng-click="lol(thick)" class="select-show">TnT</a></li>
    <li><a swapit ng-click="lol(seldon)" class="select-show">Seldon</a></li>
    <li><a swapit ng-click="lol(hit)" class="select-show">HitMan</a></li>
    <li><a swapit ng-click="lol(community)" class="select-show">Community</a></li>
</ul>

.directive('swapit', function() {

  return {
    restrict : 'A',

    link : function(scope, elem) {

      var currentState = true;

      elem.on('click', function() {
        console.log('You clicked me!');

        if(currentState === true) {
          console.log('It is on!');
          angular.element(elem).addClass('active');
        } else {
          console.log('It is off!');
          angular.element(elem).removeClass('active');
        }

        currentState = !currentState;

      });


    }
  };
});

2 个答案:

答案 0 :(得分:12)

如果使用隔离范围和ng-class

,则可以避免DOM操作并允许重用

<强>指令:

.directive('swapit', function(){
  return {
    restrict: 'E',
    replace: true,
    transclude: true,
    scope: {
      active: '='
    },
    template: '<a ng-click="active = $id" ng-class="{active: $id === active}" ng-transclude></a>'
  }
})

<强> HTML:

<swapit active="active">Still got game</swapit>
<swapit active="active">TnT</swapit>
...

通过使用隔离范围,每个指令元素都有自己的范围和唯一的ID,可以通过scope.$id访问。单击指令元素时,可以将此值分配给active范围变量,该变量在指令之间共享。

ng-click="active = $id"

然后,您可以使用ng-class和一个表达式来确定每个指令元素的作用域ID是否与当前活动作用域ID的作用域匹配:

ng-class="{active: $id === active}"

查看此demo,它与您的实施更匹配(尽管不是100%)。

答案 1 :(得分:2)

这是一个执行该操作的指令:


<子> 顺便说一句,您可以为可切换组指定一个名称,这样您就可以在同一页面上有多个“菜单”(没有一个干扰另一个)。例如: -

<li ... toggle="site-menu">Page 1</li>
<li ... toggle="site-menu">Page 2</li>
...
<li ... toggle="whatever-submenu">Option 1</li>
<li ... toggle="whatever-submenu">Option 2</li>

app.directive('toggle', function () {
  var TOGGLE_CLASS = 'selected';
  var groups = {};

  function addElement(groupName, elem) {
    var list = groups[groupName] || (groups[groupName] = []);
    if (list.indexOf(elem) === -1) {
      list.push(elem);
    }
  }

  function removeElement(groupName, elem) {
    var list = groups[groupName] || [];
    var idx = list.indexOf(elem);
    if (idx !== -1) {
      list.splice(idx, 1);
    }
  }

  function setActive(groupName, elem) {
    angular.forEach(groups[groupName], function (el) {
      el.removeClass(TOGGLE_CLASS);
    });
    elem.addClass(TOGGLE_CLASS);
  }

  return {
    restrict: 'A',
    link: function postLink(scope, elem, attrs) {
      var groupName = attrs.toggle || 'default';
      addElement(groupName, elem);

      elem.on('click', function () {
        setActive(groupName, elem);
      });

      scope.$on('$destroy', function () {
        removeElement(groupName, elem);
      });
    }
  };
});

你可以像这样使用它:

<a href="" toggle="test" ng-repeat="x in [1,2,3,4,5]">Link {{$index + 1}}</a>

另请参阅此 short demo