Search-by filter in Angular.js,
Asked Answered
B

4

10

I am new to this framework, hence practicing Angularjs and following the tutorials available on the website.

there is an example were we can search the data present in table, the example is as follows,

<!DOCTYPE html>
<html ng-app="SmartPhoneApp">
<head>
    <title>Smart phone Angular</title>      
    <script type="text/javascript" src="D:/Rahul Shivsharan/Installers/AngularJS/angular.js"></script>
    <script type="text/javascript">
        var smartPhoneApp = angular.module("SmartPhoneApp",[]);

        smartPhoneApp.controller("phoneCtrl",function($scope){
            $scope.phones = [
                {
                    "modelName" : "LUMIA 520",
                    "companyName" : "NOKIA"
                },
                {
                    "modelName" : "GALAXY S Series",
                    "companyName" : "SAMSUNG"
                },
                {
                    "modelName" : "CANVAS",
                    "companyName" : "MICROMAX"
                },
                {
                    "modelName" : "OPTIMUS",
                    "companyName" : "LG"                        
                }
            ];

        });
    </script>   
</head>
<body>  
    Search by Model Name : <input ng-model="comp.modelName" />  
    Search by Company : <input ng-model="comp.companyName" />   
    <div ng-controller="phoneCtrl">
        <table ng-repeat="phone in phones | filter: comp">
            <tr>
                <td>{{phone.modelName}}</td>
                <td>{{phone.companyName}}</td>
            </tr>
        </table>
    </div>
</body>
</html>

Here in the above code i am able to search the phone using two different inputs i.e. search by model Name and search by company Name , the above code runs fine,

But what if i need to search by using the type of search present in the select options,

the code is as follows

<!DOCTYPE html>
<html ng-app="EmployeeApp">
<head>
    <title>Orderring People</title>     
    <script type="text/javascript" src="D:/Rahul Shivsharan/Installers/AngularJS/angular.js"></script>
    <script type="text/javascript">
        var employeeApp = angular.module("EmployeeApp",[]);
        employeeApp.controller("empCtrl",function($scope){
            $scope.employees = [
                {
                    "name" : "Mahesh Pachangane",
                    "company" : "Syntel India Pvt. Ltd",
                    "designation" : "Associate"
                },
                {
                    "name" : "Brijesh Shah",
                    "company" : "Britanica Software Ltd.",
                    "designation" : "Software Engineer"
                },
                {
                    "name" : "Amit Mayekar",
                    "company" : "Apex Solutions",
                    "designation" : "Human Resource"
                },
                {
                    "name" : "Ninad Parte",
                    "company" : "Man-made Solutions",
                    "designation" : "Senior Architect"
                },
                {
                    "name" : "Sunil Shrivastava",
                    "company" : "IBM",
                    "designation" : "Project Lead"
                },
                {
                    "name" : "Pranav Shastri",
                    "company" : "TCS",
                    "designation" : "Senior Software Engineer"
                },
                {
                    "name" : "Madan Naidu",
                    "company" : "KPMG",
                    "designation" : "Senior Associate"
                },
                {
                    "name" : "Amit Gangurde",
                    "company" : "Amazon",
                    "designation" : "Programe Manager"
                }   
            ];
            $scope.orderProp="name";                
        });
    </script>   
</head>
<body ng-controller="empCtrl">      
    <table>
        <tr>
            <td align="right">Search :</td>
            <td><input ng-model="query" /></td>
        </tr>           
        <tr>
            <td align="right">Search By :</td>
            <td>
                <select ng-model="query">
                    <option value="name">NAME</option>
                    <option value="company">COMPANY</option>
                    <option value="designation">DESIGNATION</option>
                </select>   
            </td>
        </tr>
    </table>
    <hr>
    <div>
        <table>
            <tr>
                <th>Employee Name</th>
                <th>Company Name</th>
                <th>Designation</th>
            </tr>
            <tr ng-repeat="emp in employees | filter:query">
                <td>{{emp.name}}</td>
                <td>{{emp.company}}</td>
                <td>{{emp.designation}}</td>
            </tr>
        </table>
    </div>
</body>

From the above code you can see that i am trying to achieve is search employee by "Name", "Company" or "Designation" present in the selection box,

but i am going wrong here,

the ng-model query doesn't picks up the right mapping, or may be i am doing in a wrong way,

can you please tell me how will i achieve this,

which part of the code should i change

Bireme answered 25/10, 2013 at 8:34 Comment(0)
J
28

I've created a plunkr. You can define properties on the search query to filter by. In the select you choose the property you want to filter by and assign it to the search query.

http://plnkr.co/edit/XklvXtc1AZpndjLvXrh8?p=preview

Jammie answered 25/10, 2013 at 10:15 Comment(0)
I
4

An example you refer to uses object to specify filter keys, while your code always sends a string, and this is the main issue cause.

Let's assume I've typed "e" into search field. Without "Search by" selected, the filter would search for "e" in every key value. When we select value from "Search by", query string becomes current option's value ("name", "company" or "designation"), and will proceed in the same scenatio as "e", except without any result, because there aren't any matches in test data.

The proper way to choose "search by" would be contructing an object with a single key named as chosen option, equal to search query. So, if the user searches for name with "sh", it will be:

{
    name: "sh"
}

In case when no option chosen yet, the property should be named "$", this way filter will search among all properties.

I've fixed the code to work as intended (link). How you implement this is another question, but I went by defining queryFilter object on $scope, with getter which returns object of desired format.

.controller("empCtrl", function($scope) {
  Object.defineProperty($scope, "queryFilter", {
      get: function() {
          var out = {};
          out[$scope.queryBy || "$"] = $scope.query;
          return out;
      }
  })
...
<body ng-controller="empCtrl">      
    <table>
        <tr>
            <td align="right">Search :</td>
            <td><input ng-model="query" /></td>
        </tr>           
        <tr>
            <td align="right">Search By :</td>
            <td>
                <select ng-model="queryBy">
                    <option value="name">NAME</option>
                    <option value="company">COMPANY</option>
                    <option value="designation">DESIGNATION</option>
                </select>   
            </td>
        </tr>
    </table>
    <hr>
    <div>
        <table>
            <tr>
                <th>Employee Name</th>
                <th>Company Name</th>
                <th>Designation</th>
            </tr>
            <tr ng-repeat="emp in employees | filter:queryFilter">
                <td>{{emp.name}}</td>
                <td>{{emp.company}}</td>
                <td>{{emp.designation}}</td>
            </tr>
        </table>
    </div>
</body>
Installation answered 25/10, 2013 at 10:3 Comment(0)
T
1

Simple and flexible jsfiddle.

Can mention the filter fields also

filterFields: [
  "name",
  "company"
]
Tineid answered 23/1, 2018 at 11:48 Comment(0)
S
0

If you want Flipkart-like search use this. I have used the above jsfiddle code and modified it:

HTML:

<div ng-app="myapp" ng-controller="myctrl">
    <input type="text" ng-model="filter_text">
    <ul>
        <li ng-repeat="item in items | myfilter:filter_text">
            {{item}}
        </li>
        
    </ul>
</div> 

Filter.js:

angular.module('myapp', []).filter('myfilter', function($filter){
    return function(input, text){
     var filteredArray=[];
     var filteredArray1=[];
     var filteredArray2=[];
        filteredArray = $filter('filter')(input,text);
        for(var k=0;k<filteredArray.length; k++){
            if (filteredArray[k].match("^"+text)) {
                         filteredArray1.push(filteredArray[k]);
                    }else{
            filteredArray2.push(filteredArray[k]);
          }
        }
        
          
       return filteredArray1.concat(filteredArray2)
    };
});

Controller.js:

function myctrl($scope){
    $scope.filter_text = 'a';
    $scope.items = [
        'abc',
        'bca',
        'baby ama',
        'amazon','zon','zoom'
    ];
}
Springspringboard answered 23/7, 2020 at 14:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.