How to query a JSON object - angularjs

In my AngularJS web app, How can I query a JSON object ?
For example in the below JSON object how can I find the value of reportTypeLabel where reportTypeId=3
JSON:
[
{
reportTypeId:5,
reportTypeCode:"FINREP",
reportTypeLabel:"Financial Reporting"
},
{
reportTypeId:9000002,
reportTypeCode:"REM HE",
reportTypeLabel:"High Earners"
},
{
reportTypeId:3,
reportTypeCode:"COREP LE",
reportTypeLabel:"Large Exposures - COREP"
}
]

You can require $filter service and do
var elements = $filter('filter')(arrayOfObjects,{reportTypeId: 3});
elements will be an array of all the elements with that 'reportTypeId'
i would recommend reading about angular filters and https://docs.angularjs.org/api/ng/service/$filter

If you're going to use data manipulation extensively, I'd highly recommend using a JS library, like underscore or lodash.
For example, using underscore:
// assuming your object is called data
var result = _.findWhere(data, {
reportTypeId: 3
}).reportTypeLabel;
// result === 'Large Exposures - COREP'

You could do this
<div ng-repeat="report in reports | filter:{reportTypeId:'3'}">
{{report.reportTypeCode}}
</div>
Working Fiddle

You can use regular filter function on array:
var items = [
{reportTypeId:5, reportTypeCode:"FINREP"},
{reportTypeId:9000002, reportTypeCode:"REM HE"}
];
var onlyMatching = items.filter(function(item){ return item.reportTypeId == 3; });
Or an angular filter in html
<div ng-repeat="item in items | filter: {reportTypeId: '3'}">{{item. reportTypeLabel}}</div>
Or an angular filter through $filter service
module.controller('ItemsCtrl', function($filter){
$scope.filtered = $filter('filter')($scope.items,{ reportTypeId: '3' });
});

Related

AngularJS, accessing ngRepeat values in filter predicate

My best attempts at finding a solution to this have come up empty. Basically I want to do something like this in my html:
<div data-ng-repeat="tag in allTags">
<h3>{{tag}}</h3>
<uib-accordion>
<div uib-accordion-group data-ng-repeat="item in displayItems | filter: tagFilter: tag">
tagFilter looks like this:
$scope.tagFilter = function(item, tag) {
if(item.tags.indexOf(tag) === -1) {
return false;
}
return true;
}
Each item in displayItems is an object that has an array of tags, so display items looks something like this:
[
{ title: "Item 1 Title", body: "Some escaped HTML Content", tags: ["tag1", "tag2", "tag3"]},
{ title: "Item 2 Title", body: "Some escaped HTML Content", tags: ["tag2", "tag4"] }
]
and I want it to appear under all headings to which it belongs. The problem is I can't figure out how to properly pass the value of 'tag' to tagFilter. In the code above the parameter tag in codeFilter is just equal to 0 no matter what.
The problem here is actually in the semantics of the Filter syntax. More specifically, the syntax you're using above is for when you're defining an Angular Filter using the ngApp.filter(...) syntax... i.e., a filter that's registered for the entire application and can be used anywhere. In that scenario the 3rd parameter in your filter statement is the value you want to pass to the registered filter.
In your case, you're defining a filter function inside your controller which changes how the filter works. Specifically, you cannot pass dynamic values to a filter function inside a controller. When you use a function as the filter expression, it has the following signature:
function(value, index, array) {}
and then gets called in the filter statement just by the function name, so:
array|filter:filterfunction - with no params or parenthesis.
value is the value of the current item (in the array) being filtered, index is the index of that item in the array, and array is the whole array being filtered. You cannot "pass" a value to this expression, but you can use a controller or scope variable if it applies. In your case it doesn't because the value you want to filter on is inside a repeater.
To achieve what you want, you need to make your $scope.tagFilter into an actual Angular Filter, like so:
ngApp.filter('tagFilter', function($filter)
{
return function(items, searchValue)
{
// initialize array to return
var filtered = [];
angular.forEach(items, function(obj)
{
// use filter to find matching tags (3rd param means EXACT search - set to False for wildcard match)
var objFilter = ($filter("filter")(obj.tags, searchValue, true))[0];
// If a matching tag was found, add it to the filtered array
if (objFilter) filtered.push(obj);
});
return filtered;
};
});
The above assumes you've saved your angular.module(...) bootstrap to a variable named ngApp. Once this filter is registered, your current filter syntax should work as expected!
Assuming displayItems is an array,
<div uib-accordion-group data-ng-repeat="item in displayItems.filter(tagFilter(tag))" >
should do the trick.
Figured out a way to do this based on this blog post: https://toddmotto.com/everything-about-custom-filters-in-angular-js/
Basically I had to create my own custom filter rather than using angulars predicate filter
The Javascript:
ng.module('faq').filter(
'tagFilter', function() {
return function(items, tag) {
return items.filter(function(item) {
if(item.tags.indexOf(tag) === -1) {
return false;
}
return true;
});
}
}
)
The HTML:
<div uib-accordion-group data-ng-repeat="item in displayItems | tagFilter: tag">
Still don't know why the original version was not working, so if anyone can answer that 10 points to them.

add a element to json array with Key/value using angular js

I have a json array object like below
$scope.Json = [{
Id:"5464",
Class:"9",
Rank:"4"
}]
I want to add a item "Name":"Vicky" to the Json. So that my result should be as below.
$scope.Json = [{
Id:"5464",
Class:"9",
Rank:"4",
Name:"Vicky"
}]
I am new to angular, can anyone help on this?
Use Array map() method.
DEMO
var json = [{ Id:"5464", Class:"9", Rank:"4" }];
json.map(function(item) {
item.Name = 'Vicky';
});
console.log(json);
First of all, the object $scope.Json is not a JSON but a string. To get a JSON, you need to parse the string like the following:
$scope.Json = JSON.parse(<string>) ;
Second, your input is a peculiar JSON as it is an array with one element (in its turn having 3 elements. I guess you wanted this:
$scope.Json = JSON.parse({ Id:"5464", Class:"9", Rank:"4" }) ;
Once you have this, you can add the element you want as:
$scope.Json.Name = "Vicky" ;

How to get specific element and orderby priority in Firebase and Angular

I have a firebase reference like this:
$scope.lessons = $firebaseArray(firebase.child('Lessons').orderByChild('courseID').equalTo($state.params.courseID));
I'm outputting the lessons like this:
<ul>
<li class="lesson" ng-if="lesson.moduleID == module.$id" ng-repeat="lesson in lessons" lessonid="{{lesson.$id}}">
<lessonedit></lessonedit>
</li>
</ul>
I need to order the lessons by priority, but when I add the orderByPriority() function to the end of the firebase reference it says I can only use one orderBy call.
I tried the filter lesson in lessons | orderByPriority but it says that filter does not exist?
Currently, you can't mix .orderByPriority() and .orderByChild() as they are different order by functions.
However, you can still solve your problem by only using .orderByPriority(), if you re-structure your data.
Structuring your data a specific way allows you query your data, as if you could use two orderBy functions.
In your case you have a location of "Lessons" that all have a push-id key of their "lesson id": /lessons/$lessonID.
You could change your structure to key off of the courseId and then the lesson_id: /lessions/$courseID/$lessonID.
The data would look like this:
{
"lessons": {
"1": {
"-K4NQTsjo3iswX4PhKUw": {
title: "My Course"
},
"-K4NAWsjo5iswX4Jk4fa": {
title: "Another Course"
}
}
"2": {
"-K4NQTsjo3iswX4PhKUw": {
title: "My Course"
},
"-K4NQPjMZVCoFRYc_1v5": {
title: "Intro to Data Structure"
}
}
}
}
Now since the key uses the courseID, we can order by by both courseID and priority:
var courseID = $state.params.courseID;
var ref = new Firebase('<my-firebase-app>.firebaseio.com/lessons');
var query = ref.child(courseID).orderByPriority();
var syncArray = $firebaseArray(query);
You can store this in a factory in your AngularJS code.
angular.module('app', ['firebase')
.constant('FirebaseUrl', '<my-firebase-app>')
.service('RootRef', ['FirebaseUrl', Firebase])
.factory('Lessons', Lessons)
.controller('MainCtrl', MainCtrl);
function Lessons(RootRef) {
return function Lessons(courseID) {
var ref = RootRef.child('Lessons');
var query = ref.child(courseID).orderByPriority();
return $firebaseArray(query);
}
}
function MainCtrl($scope, $state, Lessons) {
var courseID = $state.params.courseID;
$scope.lessons = Lessons(courseID);
}
If Priority is an attribute of lesson, you can use the angular filter orderBy like this:
<ul>
<li class="lesson"
ng-if="lesson.moduleID == module.$id"
ng-repeat="lesson in lessons | orderBy:'Priority'"
lessonid="{{lesson.$id}}">
<lessonedit></lessonedit>
</li>
</ul>
Using Firebase's new Query API, you can do this with:
var ref = new Firebase('https://your.firebaseio.com/');
ref
.orderBy('genre')
.startAt('comedy').endAt('comedy')
.orderBy('lead')
.startAt('Jack Nicholson').endAt('Jack Nicholson')
.on('value', function(snapshot) {
console.log(snapshot.val());
});
Note that the new Query API is still in beta, so things may change before it's officially released.
See this jsbin for a similar query on Firebase's sample data set.
You can check the original Post of Frank van Puffelen here

remove double results value from forEach (angular js)

there is this thing who i am not figuring out,
i have a controller that return me an array of products propriety, that populate a field, so far i have done this:
$scope.categoryForFilter=[];
//product load
ProductService.listProducts().then(function(data) {
$scope.products = {
count: data.count,
list: data.aaData,
length: data.aaData.length
};
$scope.products.list.forEach(function (element) {
$scope.categoryForFilter.push({"id": element.category.id, "label": element.category.label})
});
});
but in this way i have multiple element.category.label in the options field that in my view is the following:
<select ng-model="categoryForFilter" ng-options="cat.label for cat in categoryForFilter" st-search="cat.label">
<option></option>
</select>
so how can i filter the results who have the same value in the array? anyone can help please?
You can use the unique filter, which is part of Angular UI.
You can also use this filter using lodash:
app.filter('unique', function() {
return function (arr, field) {
return _.uniq(arr, function(a) { return a[field]; });
};
});
Source
There is a real easy way to this by using lib like lodash with the function "uniq":
$scope.categoryForFilterWithUniqLabel = _.uniq($scope.categoryForFilter, 'label');

Filter on Onsen UI lazy repeat?

Is there a way to apply a search filter on an Onsen UI lazy repeat list ?
If we use for instance <input ng-model="search.$">
We can't directly apply | filter:search as it is not an ng-repeat.
Any idea ?
Thank you.
You need to filter the results return by the delegate object:
Simple example:
$scope.MyDelegate = {
configureItemScope: function(index, itemScope) {
itemScope.name = $scope.filteredItems[index].name;
},
calculateItemHeight: function(index) {
return 44;
},
countItems: function() {
return $scope.filteredItems.length;
}
};
In this codepen a large list of countries is filtered in this way:
http://codepen.io/argelius/pen/VLdGxZ

Resources