如何响应点击 AngularJS 指令中的复选框? [英] How to respond to clicks on a checkbox in an AngularJS directive?

查看:21
本文介绍了如何响应点击 AngularJS 指令中的复选框?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 AngularJS directive,它在以下模板中呈现实体集合:>

I have an AngularJS directive that renders a collection of entities in the following template:

<table class="table">
  <thead>
    <tr>
      <th><input type="checkbox" ng-click="selectAll()"></th>
      <th>Title</th>
    </tr>
  </thead>
  <tbody>
    <tr ng-repeat="e in entities">
      <td><input type="checkbox" name="selected" ng-click="updateSelection($event, e.id)"></td>
      <td>{{e.title}}</td>
    </tr>
  </tbody>
</table>

如您所见,它是一个

,其中可以使用自己的复选框单独选择每一行,也可以使用位于
中的主复选框一次选择所有行>.非常经典的用户界面.

As you can see, it's a <table> where each row can be selected individually with its own checkbox, or all rows can be selected at once with a master checkbox located in the <thead>. Pretty classic UI.

最好的方法是:

  • 选择单行(即勾选复选框时,将所选实体的id添加到内部数组中,并在包含要反映的实体的
中添加CSS类其选定状态)?
  • 一次选择所有行?(即对
  • 中的所有行执行前面描述的操作)
    • Select a single row (i.e. when the checkbox is checked, add the id of the selected entity to an internal array, and add a CSS class to the <tr> containing the entity to reflect its selected state)?
    • Select all rows at once? (i.e. do the previously described actions for all rows in the <table>)

    我当前的实现是在我的指令中添加一个自定义控制器:

    My current implementation is to add a custom controller to my directive:

    controller: function($scope) {
    
        // Array of currently selected IDs.
        var selected = $scope.selected = [];
    
        // Update the selection when a checkbox is clicked.
        $scope.updateSelection = function($event, id) {
    
            var checkbox = $event.target;
            var action = (checkbox.checked ? 'add' : 'remove');
            if (action == 'add' & selected.indexOf(id) == -1) selected.push(id);
            if (action == 'remove' && selected.indexOf(id) != -1) selected.splice(selected.indexOf(id), 1);
    
            // Highlight selected row. HOW??
            // $(checkbox).parents('tr').addClass('selected_row', checkbox.checked);
        };
    
        // Check (or uncheck) all checkboxes.
        $scope.selectAll = function() {
            // Iterate on all checkboxes and call updateSelection() on them??
        };
    }
    

    更具体地说,我想知道:

    More specifically, I wonder:

    • 上面的代码是属于控制器还是应该放在link函数中?
    • 鉴于 jQuery 不一定存在(AngularJS 不需要它),什么是 DOM 遍历的最佳方式?如果没有 jQuery,我很难选择给定复选框的父 <tr>,或者选择模板中的所有复选框.
    • $event 传递给 updateSelection() 似乎不太优雅.没有更好的方法来检索刚被点击的元素的状态(选中/未选中)吗?
    • Does the code above belong in a controller or should it go in a link function?
    • Given that jQuery is not necessarily present (AngularJS doesn't require it), what's the best way to do DOM traversal? Without jQuery, I'm having a hard time just selecting the parent <tr> of a given checkbox, or selecting all checkboxes in the template.
    • Passing $event to updateSelection() doesn't seem very elegant. Isn't there a better way to retrieve the state (checked/unchecked) of an element that was just clicked?

    谢谢.

    推荐答案

    这就是我一直在做这类事情的方式.Angular 倾向于对 dom 进行声明式操作,而不是命令式操作(至少我一直在使用它).

    This is the way I've been doing this sort of stuff. Angular tends to favor declarative manipulation of the dom rather than a imperative one(at least that's the way I've been playing with it).

    标记

    <table class="table">
      <thead>
        <tr>
          <th>
            <input type="checkbox" 
              ng-click="selectAll($event)"
              ng-checked="isSelectedAll()">
          </th>
          <th>Title</th>
        </tr>
      </thead>
      <tbody>
        <tr ng-repeat="e in entities" ng-class="getSelectedClass(e)">
          <td>
            <input type="checkbox" name="selected"
              ng-checked="isSelected(e.id)"
              ng-click="updateSelection($event, e.id)">
          </td>
          <td>{{e.title}}</td>
        </tr>
      </tbody>
    </table>
    

    在控制器中

    var updateSelected = function(action, id) {
      if (action === 'add' && $scope.selected.indexOf(id) === -1) {
        $scope.selected.push(id);
      }
      if (action === 'remove' && $scope.selected.indexOf(id) !== -1) {
        $scope.selected.splice($scope.selected.indexOf(id), 1);
      }
    };
    
    $scope.updateSelection = function($event, id) {
      var checkbox = $event.target;
      var action = (checkbox.checked ? 'add' : 'remove');
      updateSelected(action, id);
    };
    
    $scope.selectAll = function($event) {
      var checkbox = $event.target;
      var action = (checkbox.checked ? 'add' : 'remove');
      for ( var i = 0; i < $scope.entities.length; i++) {
        var entity = $scope.entities[i];
        updateSelected(action, entity.id);
      }
    };
    
    $scope.getSelectedClass = function(entity) {
      return $scope.isSelected(entity.id) ? 'selected' : '';
    };
    
    $scope.isSelected = function(id) {
      return $scope.selected.indexOf(id) >= 0;
    };
    
    //something extra I couldn't resist adding :)
    $scope.isSelectedAll = function() {
      return $scope.selected.length === $scope.entities.length;
    };
    

    EDIT:getSelectedClass() 需要整个实体,但仅使用实体的 id 调用它,现在已更正

    EDIT: getSelectedClass() expects the entire entity but it was being called with the id of the entity only, which is now corrected

    这篇关于如何响应点击 AngularJS 指令中的复选框?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆