1

AngularJS でチェックボックスの階層を作成しようとしています。子のチェックボックスを自動的にチェックする親のチェックボックスを作成できます。子のチェックボックスを手動でチェックすると、その子 (親の孫) のチェックボックスが更新されます。ただし、親のチェックボックスをクリックしても、孫のチェックボックスは更新されません。

親のチェックボックスが孫のチェックボックスを更新するように JavaScript を追加する前に、もっと簡単な方法があるかどうか知りたいです。これが私のコードとjsFiddleです。

<div ng-app="">
    <strong>Parent</strong> (will check all Child boxes):
    <input type="checkbox" ng-model="parent" />
    <br/>
    <strong>Child 1</strong>:
    <input type="checkbox" ng-checked="parent" />
    <br />
    <strong>Child 2</strong>:
    <input type="checkbox" ng-checked="parent" />
    <br />
    <strong>Child 3</strong> (will check all Grandchild boxes):
    <input type="checkbox" ng-checked="parent" ng-model="child" />
    <br />
    <strong>Grandchild 1</strong>:
    <input type="checkbox" ng-checked="child" />
    <br />
    <strong>Grandchild 2</strong>:
    <input type="checkbox" ng-checked="child" />
    <br />
    <strong>Grandchild 3</strong>:
    <input type="checkbox" ng-checked="child" />
</div>

どんな助けでも大歓迎です!

また、「angularjs-ng-checked」というタグを作成して、担当者が 1500 人いる人が助けてくれませんか? それは素晴らしいでしょう!

4

2 に答える 2

3

残念ながら、これ以上簡単な方法はありません。

github経由のMiskoから:

...あなたがやろうとしていることは意味がないと思います。ng-checked は一方向のデータ バインディングを作成しますが、ng-model は双方向のデータ バインディングを作成します。本質的に、同じ入力要素に接続された 2 つのモデルがあり、それは間違っていると思います。ng-model と ng-checked は排他的に使用する必要があると思います。つまり、どちらか一方を使用する必要がありますが、一緒には使用しないでください。

ディレクティブを使用したり、コントローラーで自分でチェックを同期したりする以外に、多くのオプションはありません。

于 2013-04-24T14:45:46.207 に答える
0

私はいくつかいじり回してきました (笑)、かなり一般的な解決策を思いつきました...つまり、ネストされたチェックボックスを必要な数だけ持つことができます。私が従っているいくつかの奇妙な慣行があると確信しており、パフォーマンスを向上させることができる領域があるかもしれません-これは間違いなく多くのオブジェクトをループしています-だから、自由に批判してください! フィードバックをお待ちしております。

コードはこのjsFiddleにあります。こちらにも載せておきます。

HTML

<!DOCTYPE html>
<html>
  <head>
    <script src="../js/angularjs106.js"></script>
    <script src="angular_checkbox.js"></script>
    <link rel="stylesheet" href="angular_checkbox.css" />
  </head>
  <body ng-app>
    <div ng-controller="Ctrl">
      <ul>
        <li>
          <input type="checkbox" value="allChecks.id" ng-model="allChecks.isChecked" ng-change="checkChange(allChecks)">
          <label>{{allChecks.id}}</label>
        </li>
        <li ng-repeat="child in allChecks.children">
          <input type="checkbox" ng-model="child.isChecked" ng-change="checkChange(child)">
          <label>{{child.id}}</label>
          <ul>
            <li ng-repeat="grandchild in child.children">
              <input type="checkbox" ng-model="grandchild.isChecked" ng-change="checkChange(grandchild)">
              <label>{{grandchild.id}}</label>
              <ul>
                <li ng-repeat="grandgrandchild in grandchild.children">
                  <input type="checkbox" ng-model="grandgrandchild.isChecked" ng-change="checkChange(grandgrandchild)">
                  <label>{{grandgrandchild.id}}</label>
                </li>
              </ul>
            </li>
          </ul>
        </li>
      </ul>
    </div>
  </body>  
</html>

JavaScript

function Ctrl($scope) { 
  function Node(id, isChecked, parent) {
    this.id = id;
    this.isChecked = isChecked;
    this.parent = parent;
    this.children = [];
  }

  var parent = new Node('ALL', true, "");
  var child1 = new Node('Child 1', true, parent);
  var gchild1 = new Node('Grandchild 1', true, child1);
  var gchild2 = new Node('Grandchild 2', true, child1);
  var gchild3 = new Node('Grandchild 3', true, child1);
  child1.children.push(gchild1, gchild2, gchild3);
  var child2 = new Node('Child 2', true, parent);
  var child3 = new Node('Child 3', true, parent);
  var child4 = new Node('Child 4', true, parent);
  var gchild4 = new Node('Grandchild 4', true, child4);
  var gchild5 = new Node('Grandchild 5', true, child4);
  var gchild6 = new Node('Grandchild 6', true, child4);
  var ggchild1 = new Node('Grandgrandchild 1', true, gchild6);
  var ggchild2 = new Node('Grandgrandchild 2', true, gchild6);
  var ggchild3 = new Node('Grandgrandchild 3', true, gchild6);
  gchild6.children.push(ggchild1, ggchild2, ggchild3);
  child4.children.push(gchild4, gchild5, gchild6);
  var child5 = new Node('Child 5', true, parent);
  parent.children.push(child1, child2, child3, child4, child5);
  $scope.allChecks = parent;

  function parentCheckChange(item) {
    for (var i in item.children) {
      item.children[i].isChecked = item.isChecked;
      if (item.children[i].children) {
        parentCheckChange(item.children[i]);
      }
    }
  }

  function childCheckChange(parent) {
    var allChecks = true;
    for (var i in parent.children) {
      if (!parent.children[i].isChecked) {
        allChecks = false;
        break;
      }
    }
    if (allChecks) {
      parent.isChecked = true;
    }
    else {
      parent.isChecked = false;
    }
    if (parent.parent) {
      childCheckChange(parent.parent);
    }
  }

  $scope.checkChange = function(item) {
    // We're handling the ALL checkbox
    if (item.id === $scope.allChecks.id) {
      parentCheckChange(item);
    }
    // We're handling the toggling of all of the children here
    else {
      if (item.children) {
        parentCheckChange(item);
      }
      childCheckChange(item.parent);
    }
  };
}

小さなCSS

ul {
  list-style: none;
}

とにかく、オブジェクトの親を見つける方法を見つけたかったのです。ネイティブ JavaScript オブジェクトは子の親オブジェクトへの参照を保持していないことが判明したため、Node というクラスを作成することにしました。ノードをインスタンス化すると、子を含むオブジェクトに親を設定できます。これを行うと、再帰は非常に簡単になります。

親があることに気付いたときに、parentCheckChange が呼び出されます。childCheckChange は、子のチェックが変更されたときに呼び出されますが (当たり前!)、親のすべての子を監視するために使用されます... すべての子がチェックされている場合は、親がチェックされていることを確認する必要があります。親がチェックされている場合、その親を (再帰的に) チェックする必要があるかどうかを確認する必要があります。

コードは少しわかりにくいかもしれませんので、わからない場合は質問してください。

于 2013-04-25T00:41:05.150 に答える