18

テーブルがあり、ユーザーは特定の列とこれらの列の特定の値に基づいて、テーブル内の行をフィルター処理することを選択できます。このフィルターを追跡するためのオブジェクト構造は次のようになります。

$scope.activeFilterAttributes = [
    {
        "columnName": "city",
        "values": ["LA", "OT", "NY"]
    },
    {
        "columnName": "weather",
        "values": ["humid", "sunny"]
    }
];

したがって、配列内のオブジェクトには「columnName」キーと「values」キーが含まれています。"columnName" はフィルターで考慮する列を示し、"values" にはフィルター値が含まれます。基本的に、上記の配列は、都市の列に値として「LA」、「OT」、または「NY」が含まれ、天気の列に値として「湿った」または「晴れ」が含まれるテーブルの行になります。これらの値を含まない他の行は表示されません。

このオブジェクトをよりよく理解するために、ユーザーが「都市」の列に「LA」または「NY」を含む行のみを表示したい場合、結果の配列は次のようになります。

$scope.activeFilterAttributes = [
    {
        "columnName": "city",
        "values": ["LA", "NY"]
    },
    {
        "columnName": "weather",
        "values": []
    }
];

ユーザーは、これらのフィルターを設定または削除します。これが発生するたびに、上記の配列が更新されます。この更新は正しく行われ、私はそれを確認しました - ここでは問題ありません。

問題は $watch() にあります。次のコードがあります。

$scope.$watch('activeFilterAttributes', function() {
    //Code that should update the rows displayed in the table based on the filter
}}

ユーザーが UI でフィルターを$scope.activeFilterAttributes更新すると、適切に更新されますが、これが更新されたときに $watch はトリガーされません。アプリケーションが初めてロードされるときにトリガーされますが、その後の更新はこれに影響しません。

これを実証するためにフィドルを作成しました: http://jsfiddle.net/nCHQV/

フィドルで$scope.infoは、いわばテーブルの行を表します。
$scope.dataフィルターを表します。
ボタンをクリックすると、フィルターが更新され (フィドルの場合はデータ)、テーブルに表示される行が更新されます (フィドルの場合は情報)。しかし、ご覧のとおり、ボタンをクリックしても情報は更新されません。

$scope.$watchオブジェクトの配列が変更されたときにトリガーされるべきではありませんか?

4

2 に答える 2

66

このメソッドは、2 つのオブジェクトが単に同じ参照を共有するのではなく、等しいことを確認する$watchというオプションの 3 番目のパラメーターを受け取ります。これは、参照チェックよりもコストのかかる操作であるため、デフォルトの動作ではありません。ウォッチはまだ同じオブジェクトを参照しているため、トリガーされていません。objectEquality

詳細については、ドキュメントを参照してください。

$scope.$watch('activeFilterAttributes', function() {
  // ...
}, true); // <-- objectEquality

そのパラメータを追加すると、すべてうまくいきます。

于 2013-03-30T17:36:15.760 に答える
5

AngularJS 1.1.4 では、配列やその他のコレクションで使用するために関数が追加されたため、受け入れられた回答は少し古くなっています。これは、deep-equality フラグを true に設定した場合$WatchCollectionよりもはるかに安価です。$Watch

そのため、この新しい機能はほとんどの状況で好まれています。

関数間のより詳細な違いについては、この記事を参照してください$watch

于 2015-07-06T13:45:25.500 に答える