filter by multiple values angularjs - angularjs

I would like to perform the filter and get the count of the resulted rows in js file
Filter by
1) locationId and
2) startDate between introductoryPeriodStart and introductoryPeriodEnd.
The following statement is giving synatx error. Could somebody please give me the right statement.
$scope.NewEmps = $filter('filter')($scope.Summary.CorpEmployees, { locationId: $scope.selectedItem.Label } | { startDate:$scope.Model.introductoryPeriodStart:$scope.Model.introductoryPeriodEnd}).length;
Code :
DashBoardModule.controller('DashBoardController', ['$scope','$filter', 'DashBoardModuleService', function ($scope,$filter, DashBoardModuleService) {
$scope.SelectedItems = {};
$scope.NewEmps;
$scope.Qualfd;
$scope.Scred;
$scope.submtd8850MisinDocs;
$scope.DocsRecvd8850;
$scope.DocsSubmtd8850;
$scope.Approved;
$scope.Denied;
$scope.NeedMoreInfo;
$scope.selectedItem;
var Ein = '0000000';
DashBoardModuleService.GetDashBoardSummary(Ein).then(function (response) {
// $scope.Summary = JSON.stringify(response.data.Summary);
$scope.Summary = response.data.Summary;
$scope.corporateId = response.data.Summary.corporateId;
$scope.dropboxitemselected = function (item) {
$scope.selectedItem = item;
}
console.log($scope.Summary);
});
$('#txtDateRange').on('apply.daterangepicker', function (ev, picker) {
$scope.isRefreshing = true;
$scope.Model.introductoryPeriodEnd = $filter('date')(new Date(picker.endDate), 'MM/dd/yyyy');
$scope.Model.introductoryPeriodStart = $filter('date')(new Date(picker.startDate), 'MM/dd/yyyy');
$scope.Model.typeAvailability = picker.chosenLabel === "Custom Range" ? "Custom" : picker.chosenLabel;
$scope.$apply();
console.log($scope.Model.introductoryPeriodEnd);
console.log($scope.Model.introductoryPeriodStart);
$scope.FilterByDate();
});
angular.element(document).ready(function () {
var dateConfiguration = new Date();
$('#txtDateRange').daterangepicker({
locale:{
format: 'MM/DD/YYYY'
},
autoApply: true
});
loadChartCallCenter();
loadChartHumanEfits();
loadChartQualificationSource(362, 100, 88);
});
$scope.greaterThan = function (prop, val) {
return function (item) {
return item[prop] > val;
}
};
$scope.lessThan = function (prop, val) {
return function (item) {
return item[prop] < val;
}
};
$scope.FilterByDate = function () {
console.log($scope.selectedItem);
console.log($scope.selectedItem.Label);
console.log($scope.Model.introductoryPeriodStart);
console.log($scope.Summary.CorpEmployees);
$scope.NewEmps = $scope.$eval("Summary.CorpEmployees | filter:{locationId:selectedItem.Label} | filter:greatherThan('startDate',Model.introductoryPeriodStart) | filter:lessThan('startDate',Model.introductoryPeriodEnd)").length;
}
};
}]);

You have few errors:
0- The date (greather / less) filters are not defined.
1- You can't use in this way.
So:
0- Define greatherThan
$scope.greaterThan = function(prop, val){
return function(item){
return item[prop] > val;
}
};
1- Define lessThan
$scope.lessThan = function(prop, val){
return function(item){
return item[prop] < val;
}
};
2- Use $scope.$eval
$scope.size = $scope.$eval("elements | filter:{locationId:location} | filter:greatherThan('startDate',initDate) | filter:lessThan('startDate',endDate)").length;
I updated with a better approach. Check this:
I combine lessThan with greatherThan in a only one: inRangeDate. Plus, if it is not a date I will automatically cast to date.
$scope.inRangeDate = function (prop, init, end) {
return function(item){
init = init instanceof Date ? init : new Date(init);
end = end instanceof Date ? end : new Date(end);
return item[prop] > init && item[prop] < end;
}
};
Check this Plunkr: http://plnkr.co/edit/bxPdNAUjV6I0uuJb8iRp?p=preview (I apply it on the $scope.size)
0. The first approach is in Version 4 of Plunkr
1. The inRangeDate approach is in Version 5 of same Plunkr

Related

Filtering dates to within 7 days

I have a working date filter that accepts a date string like 2018-02-09T19:35:54+00:00 and orders events by date. I would like my filter to only push items in the next 7 days. I feel like I have a basic arithmetic error in my code.
function dashCalDateFilter() {
return function(collection, key) {
let output = [];
let keys = [];
let sevenDays = Date.now() + 604800000;
angular.forEach(collection, function(item) {
var ikey = item[key];
if (keys.indexOf(ikey) === -1) {
keys.push(ikey);
item['isFirst'] = true;
}
console.log(item.start_time);
if (Date.now() - Date.parse(item.start_time) < sevenDays){
output.push(item);
};
});
return output;
};
}
export default dashCalDateFilter;
My math was a bit off. Here is the working version
function dashCalDateFilter() {
return function(collection, key) {
let output = [];
let keys = [];
let sevenDays = 604800000;
angular.forEach(collection, function(item) {
var ikey = item[key];
if (keys.indexOf(ikey) === -1) {
keys.push(ikey);
item['isFirst'] = true;
}
if ((Date.parse(item.start_time) - Date.now()) < 604800000){
output.push(item);
} else {
console.log('in >7 days');
console.log(Date.parse(item.start_time) - Date.now());
};
});
return output;
};
}
export default dashCalDateFilter;

How to make a filter attached to $scope of a controller (angular)?

I wrote a litlle program in angular using ui-select. And I wrote a filter that do an OR search in different fields.
Here is my original filter : (whic works perfectly)
app.filter('orSearchFilter', function($parse) {
return function(items, props) {
var out = [];
if (angular.isArray(items)) {
var keys = Object.keys(props);
items.forEach(function(item) {
var itemMatches = false;
for (var i = 0; i < keys.length; i++) {
var prop = $parse(keys[i])(item);
var text = props[keys[i]].toLowerCase();
if (prop && prop.toString().toLowerCase().indexOf(text) !== -1) {
itemMatches = true;
break;
}
}
if (itemMatches) {
out.push(item);
}
});
} else {
out = items;
}
return out;
};
});
And here is my original plunker (which works) : http://plnkr.co/edit/IdqO5dtLXmC6gtqLxRdP?p=preview
The problem is that my filter won't be generic and I will use it in my final code just inside its controller. So, I want to attach it.
Here is the new version of the filter which is attached to the controller : (I didn't do any change...)
$scope.orSearchFilter = function($parse) {
return function(items, props) {
var out = [];
if (angular.isArray(items)) {
var keys = Object.keys(props);
items.forEach(function(item) {
var itemMatches = false;
for (var i = 0; i < keys.length; i++) {
var prop = $parse(keys[i])(item);
var text = props[keys[i]].toLowerCase();
if (prop && prop.toString().toLowerCase().indexOf(text) !== -1) {
itemMatches = true;
break;
}
}
if (itemMatches) {
out.push(item);
}
});
} else {
out = items;
}
return out;
};
};
Finally, in my html, I called this new filter by using this line :
<ui-select-choices group-by="groupByLetter"
repeat="contract in (contracts |
filter : orSearchFilter(contracts, {id.id: $select.search, policy.info.name : $select.search } ) |
orderBy: 'name') track by contract.name">
{{contract.name}} - {{contract.value}} ---- {{contract.id.id}} *** {{contract.policy.info.name }}
</ui-select-choices>
Can you help me please to fix that problem and help me to attach this filter to the scope of the controller?
Thank you !
Use the $filter service to programmatically fetch your filter function.
//Don't forget to inject $filter in your controller ofcourse
$scope.orSearchFilter = $filter('orSearchFilter');
Attach the filter directly to scope:
/* REMOVE constructor function
$scope.orSearchFilter = function($parse) {
return function(items, props) {
*/
// INSTEAD
$scope.orSearchFilter = function(items, props) {
var out = [];
//...
return out;
};
//};
Of course, also be sure that $parse is added to the injectables of the controller construction function.

checkbox filter for json array in Angularjs

I have create a filter but this filter is not working with array inside array.
'http://plnkr.co/edit/oygy79j3xyoGJmiPHm4g?p=info'
Above plkr link is working demo.
app.filter('checkboxFilter', function($parse) {
var cache = { //create an cache in the closure
result: [],
checkboxData: {}
};
function prepareGroups(checkboxData) {
var groupedSelections = {};
Object.keys(checkboxData).forEach(function(prop) {
//console.log(prop);
if (!checkboxData[prop]) {
return;
} //no need to create a function
var ar = prop.split('=');
//console.log("ar is - "+ar);
if (ar[1] === 'true') {
ar[1] = true;
} //catch booleans
if (ar[1] === 'false') {
ar[1] = false;
} //catch booleans
/* replacing 0 with true for show all offers */
if(ar[0]=='SplOfferAvailable.text'){
ar[1]='true';
}else{
}
//make sure the selection is there!
groupedSelections[ar[0]] = groupedSelections[ar[0]] || [];
//at the value to the group.
groupedSelections[ar[0]].push(ar[1]);
});
return groupedSelections;
}
function prepareChecks(checkboxData) {
var groupedSelections = prepareGroups(checkboxData);
var checks = [];
//console.log(groupedSelections);
Object.keys(groupedSelections).forEach(function(group) {
//console.log("groupedSelections- "+groupedSelections);
//console.log("group- "+group);
var needToInclude = function(item) {
//console.log("item- "+item);
// use the angular parser to get the data for the comparson out.
var itemValue = $parse(group)(item);
var valueArr = groupedSelections[group];
//console.log("valueArr- "+valueArr);
function checkValue(value) { //helper function
return value == itemValue;
}
//check if one of the values is included.
return valueArr.some(checkValue);
};
checks.push(needToInclude); //store the function for later use
});
return checks;
}
return function(input, checkboxData, purgeCache) {
if (!purgeCache) { //can I return a previous 'run'?
// is the request the same as before, and is there an result already?
if (angular.equals(checkboxData, cache.checkboxData) && cache.result.length) {
return cache.result; //Done!
}
}
cache.checkboxData = angular.copy(checkboxData);
var result = []; // this holds the results
//prepare the checking functions just once.
var checks = prepareChecks(checkboxData);
input.every(function(item) {
if (checks.every(function(check) {
return check(item);
})) {
result.push(item);
}
return result.length < 10000000; //max out at 100 results!
});
cache.result = result; //store in chache
return result;
};
});
above code is for check box filter.
when i click on checkbox called "Availability" it does not filter the result.
Please help me out.
Thanks.
I think that the way you are navigating through json is wrong because if you put in this way it works
"Location": "Riyadh",
"AvlStatus": "AVAILABLE"
"Rooms": {.....
You have to go in some way through Rooms and right now I think you're not doing that

Sorting elements in an AngularFire array using a filter

I use Angular with Firebase and now stuck with error when trying to make a factory to work with filter.
app.factory('itemsFactory', ["$scope", '$rootScope', "$firebase", "simpleLogin",
function($scope, $rootScope, $firebase, simpleLogin) {
var ref = new Firebase("https://------.firebaseio.com/");
var items = $scope.items
$scope.items = [];
var sync = $firebase(ref);
$scope.items = sync.$asArray();
$rootScope.auth = simpleLogin;
return items;
}]);
app.filter('orderObjectBy',['itemsFactory', function (itemsFactory) {
return function (items) {
var filtered = [];
for (var i = 0; i < items.length; i++) {
var item = items[i];
if (item.hot) {
filtered.push(item);
}
};
for (var i = 0; i < items.length; i++) {
var item = items[i];
if (!item.hot) {
filtered.push(item);
}
};
return filtered;
};
}]);
This is the related HTML:
< tr ng-repeat="item in items | orderObjectBy:'hot' track by $index">
Here's what i got in console:
ngRepeat: item in items | orderObjectBy:"hot" track by $index
copeProvider%20%3C-%20%24scope%20%3C-%itemsFactory%20%3C-%orderObjectByFilter at Error (native)
Seems I messed up with dependency injection. But what would be the proper way to do it?
You can take advantage of AngularFire's extensibility to order the list without the need for a directive:
app.factory('HotList', function($firebase) {
function hotComparator(a,b) {
if( a.hot === b.hot ) {
// if both are hot or not, then sort by $id
return strcmp(a.$id, b.$id);
}
else {
// place hot items at the top
return a.hot? -1 : 1;
}
}
function strcmp(str1, str2) {
// http://phpjs.org/functions/strcmp/
return ((str1 == str2) ? 0 : ((str1 > str2) ? 1 : -1));
}
return function(ref) {
var list = $firebase(ref).$asArray();
function resort() {
list.sort(hotComparator);
}
list.$watch(resort);
resort();
return list;
};
});
app.controller('ctrl', function(HotList) {
// automagically sorted by hot/not and $id
$scope.list = HotList(new Firebase(URL));
});
To make your directive work in place, you will want to copy the array and call sort on the copy which will be a great deal simpler.
app.filter('orderObjectBy', function($firebase) {
function hotComparator(a,b) {
if( a.hot === b.hot ) {
// if both are hot or not, then sort by $id
return strcmp(a.$id, b.$id);
}
else {
// place hot items at the top
return a.hot? -1 : 1;
}
}
function strcmp(str1, str2) {
// http://phpjs.org/functions/strcmp/
return ((str1 == str2) ? 0 : ((str1 > str2) ? 1 : -1));
}
return function(items) {
var list = items.slice();
list.sort(hotComparator);
return list;
};
});
And your usage in the view is not quite right, so try it this way:
ng-repeat="item in items track by $id | orderObjectBy:'hot'"

How to check if expression will have a value after evaluating

Let's say I have a following template:
"foo['x'] = '{{ myVar }}';"
Is there an angular way of checking if evaluating this against my current scope will give myVar some value ? I've got an array of such small templates and I only want to include them in the document when values are truthy. I was hoping either $interpolate, $parse or $eval might come in handy here. I know for sure that $interpolate is useless. What about the other two ? Maybe it's at least possible to get the name of the assigned value/expression ?
EDIT
I wasn't specific enough. What I was trying to achieve, was checking in advance if for example template '{{ myVar }}' evaluated against the current scope will return an empty string or value of the scope variable (if it exists). The case was really specific - when traversing an array of short templates I wanted to know if a template will return as an empty string or not, and only include it in my final html if it doesn't.
I'm not sure what are you trying to achieve, but to if you want to check if myVar is truthy in current scope, you can:
{{myVar ? "aw yiss" : "nope"}}
Evaluates to "aw yiss" if myVar is truthy and "nope" otherwise.
I ended up with a modified $interpolate provider but maybe someone knows a shorter solution :
app.provider('customInterpolateProvider', [
function $InterpolateProvider() {
var startSymbol = '{{';
var endSymbol = '}}';
this.startSymbol = function(value){
if (value) {
startSymbol = value;
return this;
} else {
return startSymbol;
}
};
this.endSymbol = function(value){
if (value) {
endSymbol = value;
return this;
} else {
return endSymbol;
}
};
this.$get = ['$parse', '$sce', function($parse, $sce) {
var startSymbolLength = startSymbol.length,
endSymbolLength = endSymbol.length;
function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) {
allOrNothing = !!allOrNothing;
var startIndex,
endIndex,
index = 0,
expressions = [],
parseFns = [],
textLength = text.length,
exp;
var getValue = function (value) {
return trustedContext ?
$sce.getTrusted(trustedContext, value) :
$sce.valueOf(value);
};
var stringify = function (value) {
if (value == null) {
return '';
}
switch (typeof value) {
case 'string':
break;
case 'number':
value = '' + value;
break;
default:
value = angular.toJson(value);
}
return value;
};
var parseStringifyInterceptor = function(value) {
try {
return stringify(getValue(value));
} catch(err) {
console.err(err.toString());
}
};
while(index < textLength) {
if ( ((startIndex = text.indexOf(startSymbol, index)) !== -1) &&
((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) !== -1) ) {
exp = text.substring(startIndex + startSymbolLength, endIndex);
expressions.push(exp);
parseFns.push($parse(exp, parseStringifyInterceptor));
index = endIndex + endSymbolLength;
} else {
break;
}
}
if (!expressions.length && !text.contains(startSymbol) && !text.contains(endSymbol)) {
expressions.push(text);
}
if (!mustHaveExpression) {
var compute = function(values) {
for(var i = 0, ii = expressions.length; i < ii; i++) {
if (allOrNothing && angular.isUndefined(values[i])) {
return;
}
expressions[i] = values[i];
}
return expressions.join('');
};
return angular.extend(function interpolationFn(context) {
var i = 0;
var ii = expressions.length;
var values = new Array(ii);
try {
if (ii && !parseFns.length) {
return expressions[0];
} else {
for (; i < ii; i++) {
values[i] = parseFns[i](context);
}
return compute(values);
}
} catch(err) {
console.err(err.toString());
}
}, {
exp: text,
expressions: expressions,
$$watchDelegate: function (scope, listener, objectEquality) {
var lastValue;
return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) {
var currValue = compute(values);
if (angular.isFunction(listener)) {
listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope);
}
lastValue = currValue;
}, objectEquality);
}
});
}
}
return $interpolate;
}];
}
]);
Lines below were added because in some cases I have a predefined text in my short template and I always want to render it :
if (!expressions.length && !text.contains(startSymbol) && !text.contains(endSymbol)) {
expressions.push(text);
}
if (ii && !parseFns.length) {
return expressions[0];
} else {

Resources