Chapter 2: Building a search filter from scratch

HTML

<script src="https://code.angularjs.org/1.3.2/angular.min.js"></script>
<div ng-app="myApp">
    <div ng-controller="Ctrl">
        <input ng-model="search.name" 
               placeholder="Name"
               required />
        <input ng-model="search.number" 
               placeholder="Number"
               required />
        <p ng-repeat="user in users | userSearch : search">
            {{ user.firstName }} {{ user.lastName }}
        </p>
    </div>
</div>

JavaScript

angular.module('myApp', [])
.controller('Ctrl', function ($scope) {
    $scope.users = [
        {
            firstName: 'John',
            lastName: 'Stockton',
            number: '12'
        }, 
        {
            firstName: 'Michael',
            lastName: 'Jordan',
            number: '23'
        }, 
        {
            firstName: 'Allen',
            lastName: 'Iverson',
            number: '3'
        }
    ];
})
.filter('userSearch', function () {
    return function (users, search) {
        var matches = [];
        angular.forEach(users, function (user) {
            if (!angular.isDefined(users) || 
                !angular.isDefined(search)) {
                return false;
            }
            // initialize match conditions
            var nameMatch = false,
                numberMatch = false;
            if (angular.isDefined(search.name) && 
                search.name.length > 0) {
                // substring of first or last name will match
                if (angular.isDefined(user.firstName)) {
                    nameMatch = user.firstName.indexOf(search.name) > -1;
                }
                if (angular.isDefined(user.lastName)) {
                    nameMatch = nameMatch || 
                        user.lastName.indexOf(search.name) > -1;
                }
            }
            if (angular.isDefined(user.number) && 
                angular.isDefined(search.number)) {
                // only match if number is exact match
                numberMatch = user.number === search.number;
            }
            // either match should populate the results with user
            if (nameMatch || numberMatch) {
                matches.push(user);
            }
        });
        // this is the array that will be fed to the repeater
        return matches;
    };
});