Search code examples
javascriptarraysangularjsangularjs-directiveangularjs-scope

search does not work if the terms have space


I have an angular search on multiple fields. My search works as long as there is no space in the search term. But if a field has a space, it will break. This is happening because I am trying to separate out the search terms based on space, since space comes more natural to users then comma separation or pipes or any other delimiter.

**
search for BMW special and you will see you wont have any results **

This is where in the code I am doing a split

$scope.q.split(' ').forEach(function(token) {
    matched = matched && match(car, token);
});

Here is the plunker http://plnkr.co/edit/slzYsK1ohkC1ClEEpyiB?p=info

Here is my code

index.html

<!DOCTYPE html>
<html ng-app="myapp">

<head>
    <link data-require="[email protected]" data-semver="3.1.1" rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" />
    <script data-require="angular.js@*" data-semver="1.3.0-beta.5" src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
    <script data-require="jquery@*" data-semver="2.1.1" src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script data-require="bootstrap@*" data-semver="3.1.1" src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
</head>

<body>
<div ng-controller="DemoCtrl">
    <input class="form-control" type="text" ng-model="q" placeholder="Search by year, make, model" />
    <br/>
    <ul>
        <li ng-repeat="car in cars | filter:filterCars">{{car.year}} {{car.make}} {{car.model}}</li>
    </ul>
</div>
</body>

</html>

script.js

// Code goes here

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

app.controller('DemoCtrl', [ '$scope', function($scope) {
    $scope.q = '';
    $scope.cars = [
        {
            year: 2006,
            make: 'BMW',
            model: 'M3'
        },
        {
            year: 2006,
            make: 'BMW',
            model: 'Z4'
        },
        {
            year: 1992,
            make: 'Mazda',
            model: 'Miata'
        },
        {
            year: 2008,
            make: 'BMW special',
            model: '750'
        }
    ];

    var match = function (item, val) {
        var regex = new RegExp(val, 'i');
        return item.year.toString().search(regex) == 0 ||
            item.make.search(regex) == 0 ||
            item.model.search(regex) == 0;
    };

    $scope.filterCars = function(car) {
        // No filter, so return everything
        if (!$scope.q) return true;
        var matched = true;

        // Otherwise apply your matching logic
        $scope.q.split(' ').forEach(function(token) {
            matched = matched && match(car, token);
        });

        return matched;
    };
}]);

Solution

  • I changed the definition of the function match to the following

    // The following function will return true if
    // the string in val is found in itme.year.toString(),
    // item.make, or item.model
    var match = function (item, val) {
      var regex = new RegExp(val, 'i');
      return item.year.toString().search(regex) >= 0 ||
             item.make.search(regex) >= 0 ||
             item.model.search(regex) >= 0;  
    };
    

    I made the change to the code in plunker and entering bmw special did return the appropriate record.