使用带有 AngularJS 的复选框过滤数组

Posted

技术标签:

【中文标题】使用带有 AngularJS 的复选框过滤数组【英文标题】:Filter Array Using Checkboxes with AngularJS 【发布时间】:2014-01-30 06:00:56 【问题描述】:

我有以下代码,我试图通过选中玩家裤子尺寸的复选框来过滤数组中的玩家。

我知道我在转发器中有数据数组,然后在数据数组元素(两个不同的 div)之外的元素中进行过滤输入,这可能是导致断开连接的原因吗?因为我注意到当我将复选框添加到转发器元素时,当我单击复选框时,我确实得到了某种形式的反馈数组。

绑定一个搜索输入框很容易实现,但是我花了太多时间来获取这个简单的复选框来过滤数据。

因此,我现在向 Angular 社区寻求有关使用复选框进行过滤的一些帮助,因为文档并没有很好地涵盖这个主题。

这里是小提琴:http://jsfiddle.net/rzgWr/1/

<div ng-controller="MyCtrl">
<div>
<div ng-repeat="pants in players | groupBy:'pants'">
    <b><input type="checkbox" ng-model="query"/>pants</b>
    <span>((players | filter:pants).length)</span>
</div>

<div>
    <ul>
    <li ng-repeat="player in players | filter:query">
        <p><b>player.name</b></p>
        <p>player.shirt player.pants, player.shoes</p>
    </li>
    </ul>    
</div>
</div>

function MyCtrl($scope, filterFilter) 
$scope.players = [
    name: 'Bruce Wayne', shirt: 'XXL', pants: '42', shoes: '12',
    name: 'Wayne Gretzky', shirt: 'XL', pants: '38', shoes: '10',
    name: 'Michael Jordan', shirt: 'M', pants: '32', shoes: '9',
    name: 'Player Two', shirt: 'XXL', pants: '42', shoes: '12'
]; 

$scope.$watch('filtered', function (newValue) 
    if (angular.isArray(newValue)) 
        console.log(newValue.length);
    
, true);    

真诚感谢任何和所有帮助/建议。

谢谢。

【问题讨论】:

您的意思是当您搜索某些内容时,复选框旁边的绑定会更新? 【参考方案1】:

编辑 2

根据 OP 的所有请求,这是最终状态。

http://jsfiddle.net/rzgWr/19/


编辑(OP添加了赏金)

根据你的赏金,这是你想要的吗?

http://jsfiddle.net/rzgWr/17/


这是你想要的吗?

http://jsfiddle.net/rzgWr/12/

模板

<div ng-controller="MyCtrl">
    <div>
      <div>
          Search: <input name="company" type="text" class="search-input" ng-model="query"/>
       </div>
    <div ng-init="pantsGroup = (players | groupBy:'pants')">
        <div ng-repeat="pants in pantsGroup" >
            <b><input type="checkbox" ng-model="usePants[$index]"/>pants</b>
            <span>((players | filter:pants).length)</span>
        </div>
    </div>

    <div>
        <ul>
        <li ng-repeat="player in players | filter:query | filter:filterPants()">
            <p><b>player.name</b></p>
            <p>player.shirt player.pants, player.shoes</p>
        </li>
        </ul>    
    </div>
    </div>
</div>

脚本

var myApp = angular.module('myApp',[]);

function MyCtrl($scope, filterFilter) 
    $scope.usePants = [];

    $scope.filterPants = function () 
        return function (p) 
            for (var i in $scope.usePants) 
                return (p.pants == $scope.pantsGroup[i] && $scope.usePants[i]);
            
        ;
    ;

    $scope.players = [
        name: 'Bruce Wayne', shirt: 'XXL', pants: '42', shoes: '12',
        name: 'Wayne Gretzky', shirt: 'XL', pants: '38', shoes: '10',
        name: 'Michael Jordan', shirt: 'M', pants: '32', shoes: '9',
        name: 'Rodman', shirt: 'XXL', pants: '42', shoes: '11',
        name: 'Jake Smitz', shirt: 'XXL', pants: '42', shoes: '12',
        name: 'Will Will', shirt: 'XXL', pants: '42', shoes: '12',
        name: 'Youasdf Oukls', shirt: 'XL', pants: '38', shoes: '10',
        name: 'Sam Sneed', shirt: 'XL', pants: '38', shoes: '10',
        name: 'Bill Waxy', shirt: 'M', pants: '32', shoes: '9',
        name: 'Javier Xavior', shirt: 'M', pants: '32', shoes: '9',
        name: 'Bill Knight', shirt: 'M', pants: '32', shoes: '9',        
        name: 'One More', shirt: 'M', pants: '32', shoes: '9',        
        name: 'Player One', shirt: 'XXL', pants: '42', shoes: '11',
        name: 'Space Cadet', shirt: 'XXL', pants: '42', shoes: '12',
        name: 'Player Two', shirt: 'XXL', pants: '42', shoes: '12'
    ]; 

    $scope.$watch('filtered', function (newValue) 
        if (angular.isArray(newValue)) 
            console.log(newValue.length);
        
    , true);    


myApp.filter('count', function() 
    return function(collection, key) 
      var out = "test";
      for (var i = 0; i < collection.length; i++) 
          //console.log(collection[i].pants);
          //var out = myApp.filter('filter')(collection[i].pants, "42", true);
      
      return out;
    
);

var uniqueItems = function (data, key) 
    var result = new Array();
    for (var i = 0; i < data.length; i++) 
        var value = data[i][key];

        if (result.indexOf(value) == -1) 
            result.push(value);
        

    
    return result;
;

myApp.filter('groupBy',
            function () 
                return function (collection, key) 
                    if (collection === null) return;
                    return uniqueItems(collection, key);
        ;
    );

【讨论】:

Words:当我现在使用来自服务器的数据尝试此功能时,过滤不再起作用,因为 ng-init 正在运行,无法在动态数据上运行表达式。关于我可以使用什么来代替 ng-init 的任何想法?谢谢。 是的,我使用了它,所以我不必将$filter 服务注入控制器。这就是您需要做的所有事情:jsfiddle.net/rzgWr/16 我想任何一种解决方案都可以,只要级联过滤缩小数组数据。理想情况下,我希望根据剩余数据更新过滤器。因此,例如,如果鞋子:M 被过滤,并且只有小号和中号的裤子尺寸保留在过滤后的数据中,那么只有小号和中号的裤子过滤器可见并可用于进一步过滤。这有帮助吗? 是的,我只是重写了那段代码。似乎工作。 jsfiddle.net/rzgWr/19 你所做的简直太棒了!您为这个 Angular 主题的论坛增加了巨大的价值,我非常高兴地奖励您! :)【参考方案2】:

完全优化的 js 代码

var myApp = angular.module('myApp',[]); var selected; var uniqueItems = function (data, key) var result = []; for (var i = 0; i < data.length; i++) var value = data[i][key]; if (result.indexOf(value) == -1) result.push(value); return result; ; var fliter = function(totalData,selectedData,equalData) var filterAfter = []; selected = false; for (var j in totalData) var p = totalData[j]; for (var i in selectedData) if (selectedData[i]) selected = true; if (i == p[equalData]) filterAfter.push(p); break; if (!selected) filterAfter = totalData; return filterAfter; function MyCtrl($scope, filterFilter) $scope.usePants = ; $scope.useShirts = ; $scope.useShoes = ; $scope.players = [ name: 'Bruce Wayne', shirt: 'XXL', pants: '42', shoes: '12', name: 'Wayne Gretzky', shirt: 'XL', pants: '38', shoes: '10', name: 'Michael Jordan', shirt: 'M', pants: '32', shoes: '9', name: 'Rodman', shirt: 'XXL', pants: '42', shoes: '11', name: 'Jake Smitz', shirt: 'XXL', pants: '42', shoes: '12', name: 'Will Will', shirt: 'XXL', pants: '42', shoes: '12', name: 'Youasdf Oukls', shirt: 'XL', pants: '38', shoes: '10', name: 'Sam Sneed', shirt: 'XL', pants: '38', shoes: '10', name: 'Bill Waxy', shirt: 'M', pants: '32', shoes: '9', name: 'Javier Xavior', shirt: 'M', pants: '32', shoes: '9', name: 'Bill Knight', shirt: 'M', pants: '32', shoes: '9', name: 'One More', shirt: 'M', pants: '32', shoes: '9', name: 'Player One', shirt: 'XXL', pants: '42', shoes: '11', name: 'Space Cadet', shirt: 'XXL', pants: '42', shoes: '12', name: 'Player Two', shirt: 'XXL', pants: '42', shoes: '12' ]; // Watch the pants that are selected $scope.$watch(function () return players: $scope.players, usePants: $scope.usePants, useShirts: $scope.useShirts, useShoes: $scope.useShoes , function (value) $scope.count = function (prop, value) return function (el) return el[prop] == value; ; ; $scope.pantsGroup = uniqueItems($scope.players, 'pants'); $scope.shirtsGroup = uniqueItems($scope.players, 'shirt'); $scope.shoesGroup = uniqueItems($scope.players, 'shoes'); var fliterType = [selected : $scope.usePants,fliter : 'pants',selected : $scope.useShirts,fliter : 'shirt',selected : $scope.useShoes,fliter : 'shoes']; var startFliter = $scope.players; for(var i in fliterType) var startFliter = fliter(startFliter,fliterType[i].selected,fliterType[i].fliter); $scope.filteredPlayers = startFliter; , true);

【讨论】:

这是另一种编写上述过滤代码的方式 我正在使用您的代码来满足我的要求。唯一的区别是我想让未过滤的对象传递给 filterType 循环。在您的代码中,您传递了作为过滤对象的 startFilter,但我想传递未过滤的对象,因此每当用户检查多个选项时,代码都会显示所选对象的所有对象。你知道我需要做什么改变才能完成吗?我尝试了不同的解决方案,但它们破坏了代码。 如果您调试该选定值,您将得到答案。例如,输入“console.log($scope.usePants);”它为选中返回 42:true;如果您想取消选择该值,您确实需要像这样设置 '42:false';

以上是关于使用带有 AngularJS 的复选框过滤数组的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS 复选框过滤器

基于复选框选择的AngularJS过滤器

使用jQuery更新复选框时,AngularJS不会刷新

如何在angularjs中使用带有嵌套ng-repeat的复选框

AngularJS ng Repeat - 使用复选框按单个对象属性筛选列表

数字数组的AngularJS复选框[重复]