Reputation: 12047
I have the below code which uses a controller
to grab the contents of a JSON file and then display the first 5 results. The code also includes a filter to allow users to search.
The filter looks for results in both name
and code
(see below JSON example), which is great. However, I'd like for the filter to do more; code
is unique, and if a match to code is found it should be displayed at the top of the list, with the remaining four results listed by name
underneath.
For example, if the user was to search for swi
, currently the five results that are listed are -
Brunswick (BRW)
Chiswick (CHK)
Derby Road (Ipswich) (DBR)
Giggleswick (GIG)
Hutton Cranswick (HUT)
What I would like is -
Swindon (SWI)
Brunswick (BRW)
Chiswick (CHK)
Derby Road (Ipswich) (DBR)
Giggleswick (GIG)
Is this possible using AngularJS, or would I be looking at using some more complex logic to get my desired results?
[
{
"name": "Abbey Wood",
"code": "ABW"
},
{
"name": "Aber",
"code": "ABE"
},
{
"name": "Abercynon",
"code": "ACY"
}
]
<!DOCTYPE html>
<html lang="en-GB" data-ng-app="tigerSelector">
<head>
<meta charset="UTF-8">
<title>Tiger | Staff CIS Selector</title>
<!-- Mobile stuff -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-capable" content="yes">
<!-- Angular JS -->
<script src="angular/angular.js"></script>
<script type="text/javascript">
var app = angular.module('tigerSelector', []);
app.controller('stationsCtrl', function($scope, $http){
$http.get('stations.json').then(function(res){
$scope.stations = res.data;
});
});
</script>
</head>
<body>
<div data-ng-controller="stationsCtrl">
<p>Filtering input:</p>
<p><input type="text" data-ng-model="search"></p>
<ul>
<li data-ng-repeat="station in stations | filter:search | orderBy:'name' | limitTo:5">
{{ station.name }} ({{ (station.code | uppercase) }})
</li>
</ul>
</div>
</body>
</html>
Upvotes: 1
Views: 79
Reputation: 3315
You can create custom filter, and iterate over your collection, and passing your search
ngModel to the filter.
Filter
(function(){
function filter(){
return function (input, search) {
var out = [];
//Map over the input
[].map.call(input || [], function(elm){
//Compare code value to search model
elm.code.toLowerCase() === search
//Push elm at the beginning of the array
? out.unshift(elm)
//Otherwise, add element to the end of the array
: out.push(elm);
});
//Return our filtered array
return out;
};
}
angular
.module('app')
.filter('myFilter', filter);
})();
Then you can call your filter into your template. You can combine multiple filter.
HTML
<p><input type="text" data-ng-model="search"></p>
<ul>
<li data-ng-repeat="station in stations | myFilter:search | filter:search | limitTo:5">
{{ station.name }} ({{ (station.code | uppercase) }})
</li>
</ul>
Upvotes: 1