Angular filter on json object - angularjs

I have a json record as country, inside country, it contains many states, I want to filter by either label or value, so the states json looks like:
$scope.states: {"s1":{"label":"Alabama","value":"Alabama"},"s2":{"label":"Alaska","value":"Alaska"},"s3":{"label":"Arizona","value":"Arizona"},"s4":{"label":"Arkansas","value":"Arkansas"},"s5":{"label":"California","value":"California"},"s6":{"label":"Colorado","value":"Colorado"},"s7":{"label":"Connecticut","value":"Connecticut"},"s8":{"label":"Delaware","value":"Delaware"},"s9":{"label":"DC","value":"DC"},"s10":{"label":"Florida","value":"Florida"},"s11":{"label":"Georgia","value":"Georgia"},"s12":{"label":"Hawaii","value":"Hawaii"},"s13":{"label":"Idaho","value":"Idaho"},"s14":{"label":"Illinois","value":"Illinois"},"s15":{"label":"Indiana","value":"Indiana"},"s16":{"label":"Iowa","value":"Iowa"},"s17":{"label":"Kansas","value":"Kansas"},"s18":{"label":"Kentucky","value":"Kentucky"},"s19":{"label":"Louisiana","value":"Louisiana"},"s20":{"label":"Maine","value":"Maine"},"s21":{"label":"Maryland","value":"Maryland"},"s22":{"label":"Massachusetts","value":"Massachusetts"},"s23":{"label":"Michigan","value":"Michigan"},"s24":{"label":"Minnesota","value":"Minnesota"},"s25":{"label":"Mississippi","value":"Mississippi"},"s26":{"label":"Missouri","value":"Missouri"},"s27":{"label":"Montana","value":"Montana"},"s28":{"label":"Nebraska","value":"Nebraska"},"s29":{"label":"Nevada","value":"Nevada"},"s30":{"label":"New Hamshire","value":"New Hamshire"},"s31":{"label":"New Jersey","value":"New Jersey"},"s32":{"label":"New Mexico","value":"New Mexico"},"s33":{"label":"New York","value":"New York"},"s34":{"label":"North Carolina","value":"North Carolina"},"s35":{"label":"North Dakota","value":"North Dakota"},"s36":{"label":"Ohio","value":"Ohio"},"s37":{"label":"Oklahoma","value":"Oklahoma"},"s38":{"label":"Oregon","value":"Oregon"},"s39":{"label":"Pennsylvania","value":"Pennsylvania"},"s40":{"label":"Puerto Rico","value":"Puerto Rico"},"s41":{"label":"Rhode Island","value":"Rhode Island"},"s42":{"label":"South Carolina","value":"South Carolina"},"s43":{"label":"South Dakota","value":"South Dakota"},"s44":{"label":"Tennessee","value":"Tennessee"},"s45":{"label":"Texas","value":"Texas"},"s46":{"label":"Utah","value":"Utah"},"s47":{"label":"Vermont","value":"Vermont"},"s48":{"label":"Virgin Islands","value":"Virgin Islands"},"s49":{"label":"Virginia","value":"Virginia"},"s50":{"label":"Washington","value":"Washington"},"s51":{"label":"West Virginia","value":"West Virginia"},"s52":{"label":"Wisconsin","value":"Wisconsin"},"s53":{"label":"Wyoming","value":"Wyoming"}}
the code for the page is:
<label class="item item-input">
<input type="text" placeholder="请输入你要寻找的省市" ng-model="searchText.$"/>
</label>
<ion-radio ng-model="create.state" ng-repeat="s in states | filter:searchText)" ng-value="s">{{s.label}}</ion-radio>
this does not work, I also tried custom filter based on another post: filter on nested objects, does not work for me

mention which field are you trying to put a filter on
filter:{'label': searchText} and ng-model="searchText" would suffice.
As you are trying to iterate over the object properties you can define a custom filter as follows .Here is the working example
.filter('customFil', function () {
return function (p, query) {
var obj = {};
for (var key in p) {
if (p.hasOwnProperty(key)) {
if (p[key].label.includes(query)) {
obj[key] = p[key];
}
}
}
return obj;
}
});

Related

AngularJs Auto Complete Search

So this works with static data, but when I push data with a $http this autocomplete does not work. The data pushes to the empty array of airport_list but something is happening when I try to use airport_list in for the autocomplete. Not sure what is is. I can only find answers which pertain to static data.
This is updated per everyones help.
Here is the controller
app.controller('selectCtrl', function($scope, $http) {
$scope.airport_list = null;
$http({
url: 'someUrl.com',
method: 'GET'
})
.then((response) => {
angular.forEach(response.data.airports, function(value, key) {
$scope.airport_list = response.data.airports;
})
$scope.airports = $scope.airport_list;
});
$scope.selectAirport = function(string) {
$scope.airport = string;
$scope.hidelist = true;
};
})
Here is the template
<div class="control">
<div>
<input
type="text"
name="airport"
id="airport"
ng-model="airport"
ng-change="searchFor(airport)"
placeholder="From..."
/>
<div class="airport-container-dropdown" ng-hide="hidelist">
<div
class="airport-list"
ng-repeat="airport in airports"
ng-click="selectAirport(airport)"
>
{{ airport.name }}
</div>
</div>
</div>
</div>
I really would like to do this without using bootstrap typeahead.
Thank you for looking at this.
I have made changes as recommended by below answers and the $http request is feeding into the autocomplete as a whole list but searching by name does not work and clicking on name sets [object, object]
this would be the code which is specific to that functionality.
$scope.searchFor = function(string) {
$scope.hidelist = false;
const output = [];
angular.forEach($scope.airport_list, function(airport) {
if (airport[0].toLowerCase().indexOf(string.toLowerCase(airport)) >=
0) {
output.push(airport);
}
});
$scope.airports = output;
};
$scope.selectAirport = function(string) {
$scope.airport = string;
$scope.hidelist = true;
};
Try this:
$scope.airport_list = response.data.airports;
What I am seeing is that you have an array: $scope.airport_list = [];
When you make your http request, you push what I would understand to be an array of airports into that array. So you end up with your airport array from the backend at the first position of $scope.airport_list, vs. $scope.airport_list being the actual list.
For your search method, you should change the following:
In your HTML:
ng-change="searchFor(airport.name)"
In your JS:
I've renamed your function and changed the input variable to be more clear. You were passing in a full airport, but treating it as a string. You need to compare your provided airport name to that of the airports in the array. So you iterate over the array, and compare each element's name property to what you pass in.
$scope.searchFor = function(airportName) {
$scope.hidelist = false;
const output = [];
angular.forEach($scope.airport_list, function(airport) {
if (airport.name.toLowerCase() === airportName) {
output.push(airport);
}
});
$scope.airports = output;
console.log($scope.airports);
};
I have provided minimal changes to your code to implement this, however I suggest you look at this SO post to filter drop down data more appropriately.
Angularjs Filter data with dropdown
If you want to simply filter out what is displayed in the UI, you can try this in your HTML template. It will provide a text field where you supply a partial of the airport name. If at least one character is entered in that box, the list will display on the page, with the appropriate filtering applied. This will avoid having to call functions on change, having a separate array, etc.
<input type="text" name="airport" id="airport" ng-model="airportSearch.name" placeholder="From..." />
<div class="airport-container-dropdown" ng-hide="!airportSearch.name">
<div class="airport-list"
ng-repeat="airport in airport_list | filter:airportSearch"
ng-click="selectAirport(airport)">
{{ airport.name }}
</div>
</div>

how to add two filters with or condition in ng-repeat Angular JS

i am using ng-repeate and in my filter i need to use one of the fields in upper bounded list that can not be refrenced by inner select filter , so i need to set filters in html block and not in js file .somthing like this:
<div ng-repeat="groupfield in gCtrl.groupingFields">
<select ng-options="c.id as c.title for c in gCtrl.columnList | filter : {available:true } || {id:groupfield.fieldName}">
</select></div>
You can pass the filter a custom function. You cannot pass arguments to the actual filter function, so the trick is to create a function that returns the filter function, and pass groupfield to that.
function MyController() {
this.customFilter = customFilter;
function customFilter(groupfield) {
return function(value, index, array) {
return value.available || groupfield.fieldName === value.id;
}
}
}
<div ng-repeat="groupfield in gCtrl.groupingFields">
<select required class="form-control" ng-model="groupfield.fieldName" ng-options="c.id as c.title for c in gCtrl.columnList | filter : groupCtrl.customFilter(groupfield)"></select>
</div>

is it possible to use a variable filter?

I'm trying to use filter who gonna change depending on a click or write on an input.
<input
name="hotelinput"
type="text"
ng-keydown="changeFilterToKeyPressed()"
ng-click="changeFilterToClicked()">
<div ng-repeat="hotel in filteredHotels = (hotels | VARIABLEFILTER | orderBy: 'country') track by $index">
...
</div>
I know that you can do filter:variable and change it in the controller but I need to change the full filter for one of my custom filters every time.
I didn't tested it but something like this could be possible
JS
if(x){
$scope.VARIABLEFILTER = $filter('myCustomFilter')
} else {
$scope.VARIABLEFILTER = $filter('myCustomFilter2')
}
I made it to work and rewrote the filter I once did in other question
http://plnkr.co/edit/LuA3hYr7mImihYnVIxqQ
.filter('applyFilter', function($filter) {
return function(input, filterToApply) {
return filterToApply === undefined ? input : $filter(filterToApply)(input)
}
})
I hope that's what you were looking for
You need ngChange instead of ngClick
<input
name="hotelinput"
type="text"
ng-model="filterKey"
ng-change="changeFilterToKeyPressed()"
ng-focus="changeFilterToClicked()">
and update your function changeFilterToKeyPressed
$scope.changeFilterToKeyPressed = function() {
$scope.VARIABLEFILTER = someUpdatesWhichYouWant($scope.filterKey); //You can use filterKey on any change
}

AngularJS Ng-Repeat Search Filter, How can i limit what properties to search for?

Currently i have a ng-repeat that writes out a rather large object per row. However, i am only wanting the search filter to scan through 5 properties and not the 20 properties the object has. Is there a way i can tell the filter to only check specific properties and ignore the rest? I was thinking something below...
<div> <input ng-model="search" type="text"/> </div>
<div ng-repeat="item in items | filter:search:property1:property2">
{{item.property1}}
</div>
Create a custom filter that allows you to have necessary parameters as you need.
app.filter('myFilter', function(){
// Just add arguments to your HTML separated by :
// And add them as parameters here, for example:
// return function(dataArray, searchTerm, argumentTwo, argumentThree) {
return function(dataArray, searchTerm) {
// If no array is given, exit.
if (!dataArray) {
return;
}
// If no search term exists, return the array unfiltered.
else if (!searchTerm) {
return dataArray;
}
// Otherwise, continue.
else {
// Convert filter text to lower case.
var term = searchTerm.toLowerCase();
// Return the array and filter it by looking for any occurrences of the search term in each items id or name.
return dataArray.filter(function(item){
var termInId = item.id.toLowerCase().indexOf(term) > -1;
var termInName = item.name.toLowerCase().indexOf(term) > -1;
return termInId || termInName;
});
}
}
});
Then in HTML
<tr ng-repeat="item in data | myTableFilter:filterText:argumentTwo:argumentThree">
Inspired from filter-by-multiple-columns-with-ng-repeat
Not sure you can do directly . I think you will have to write a function in your controller to do that .
e.g.
<div> <input ng-model="search" type="text"/> </div>
<div ng-repeat="item in items | filter:searchSpecificPpts()">
{{item.property1}}
</div>
in your controller create a function like
$scope.searchSpecificPpts(){
//Here goes the logic to filter
return filteredList;
}

Is it Item based or content based Collaborative filtering?

(Updated code)
Hi all i want to filtering items for count and quality using the filter functionality in meanjs app. then i tried many ways but unable to get the solution if any one knows the solution please help me.....
here is my plunker sample
Count All
<div class="col-md-2 form-group form-group-default">
<label>Quality</label> <select data-ng-model="searchtable.quality" id="quality" ng-options="item.quantity as item.quantity for item in descriptionyarnqualitys" class="form-control" placeholder="Quality"required><option value="">All</option></select>
</div>
The quality property is a sub property of colorshades and not of the order itself. Use searchtable.colorshades.quality model name and it works
dynamically extract the 'quality' value from the order list:
$scope.getDescriptionyarnqualitys = function() {
var qualities = {};
angular.forEach($scope.sryarnorders, function(order) {
angular.forEach(order.colorshades, function(shade) {
qualities[shade.quality]=shade.quality;
});
})
return qualities;
};
In the HTML you can call the function to extract the available qualities:
<select data-ng-model="searchtable.colorshades.quality" id="quality" ng-options="name for (name, value) in getDescriptionyarnqualitys()" class="form-control" placeholder="Quality" required>
Hope this help.

Resources