Filtering ng-repeat list using checkboxes and AngularJS

Michael Romrell picture Michael Romrell · Feb 11, 2014 · Viewed 11.9k times · Source

I've read a lot of other posts on this and they all tend to describe uniquely complicated solutions. I just want to filter a list of items based on the checkboxes I click (I need an 'AND' Filter & be able to see all items initially until a checkbox is clicked).

This seems like it should be a piece of cake with AngularJS, But I'm just not getting it. how can I modify my code to make the filtering work?

Here is my incomplete JSFiddle: http://jsfiddle.net/mromrell/qx3cD/1/

Updated Fiddle here: http://jsfiddle.net/mromrell/qx3cD/7/

Thank you in Advance!

<div ng-controller="MyCtrl">
<li class="no-decoration" ng-repeat="tech in technologyArray">
    <label>
        <input type="checkbox" ng-model="strict" />{{tech}}</label>
</li>
<hr>
<div ng-repeat="portfolioItem in portfolioArray | filter:strict" class="ng-scope">
     <h3>{{portfolioItem.name}}</h3>

</div>

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

function MyCtrl($scope) {
    $scope.technologyArray = ["HTML", "CSS", "Django", "Python", "AngularJS", "Javascript", "3rd party Payment API", "3rd party Libraries", "Jquery", "RestfulAPI", "AAAAAHH", "NodeJS", "Mongo", "Express", "Jade", "Wordpress", "MySQL", "Joomla", "Magento", "Jira"]

$scope.portfolioArray = [{
    "id": "1",
    "name": "Storm Pig",
    "technology": ["HTML", "CSS", "Django", "Python", "AngularJS", "Javascript", "3rd party Payment API", "3rd party Libraries"]
}, {
    "id": "2",
    "name": "Placer",
    "technology": ["HTML", "CSS", "Django", "Python", "AngularJS", "Javascript", "Jquery"]
}, {
    "id": "3",
    "name": "Custom Proposal App",
    "technology": ["RestfulAPI", "AAAAAHH", "AngularJS", "HTML", "CSS", "Javascript", "NodeJS", "Mongo", "Express", "Jade"]
}, {
    "id": "4",
    "name": "21 Zero",
    "technology": ["HTML", "CSS", "Wordpress", "MySQL"]
}, {
    "id": "5",
    "name": "Detour Journal",
    "technology": ["HTML", "CSS", "Joomla", "MySQL"]
}, {
    "id": "6",
    "name": "Dex Custom Websites",
    "technology": ["HTML", "CSS", "Wordpress", "MySQL", "Magento", "Jira"]
}, {
    "id": "7",
    "name": "Conversion Jump",
    "technology": ["HTML", "CSS", "Joomla", "MySQL"]
}, {
    "id": "8",
    "name": "The Canyons Pass",
    "technology": ["HTML", "CSS", "Joomla", "MySQL"]
}]

}

Answer

Matt Way picture Matt Way · Feb 11, 2014

I think I have solved it in a fairly simple way: http://jsfiddle.net/qx3cD/4/

The problem you are having is that checkboxes work on a true/false value system, while a basic filter is looking to match data. So you need to create some sort of custom filter to map the checkbox states to the data itself. I used this basic function, which simply compares checkbox states to their corresponding name, and if they are associated with the tech list.

$scope.myFunc = function(a) {
    for(tech in $scope.technologyArray){
        var t = $scope.technologyArray[tech];
        if(t.on && a.technology.indexOf(t.name) > -1){
            return true;   
        }               
    }
};

EDIT: Updated

I have updated the fiddle here: http://jsfiddle.net/qx3cD/9/

Basically two things were done. The first was that the checkboxes were watched with ng-change, so that all results were shown when no checkboxes were selected. The second was that the filter function was updated to only show items that contain all of the selected technologies.