I have the following Model and would like to display the top voted over the last 24 hours
{
"_id": {
"$oid": "56abe20fabd3fa64187b5d21"
},
"user": {
"$oid": "56a1832a36dc3d0e00c7aa3f"
},
"title": "Intel Pentium i5 Quad-Core i5-6400",
"created": {
"$date": "2016-01-29T22:05:03.574Z"
},
"votes": 1
}
So basically limiting the ng-repeat to the created field within the last 24 hours.
Filter
angular.module('savings').filter('lessThan', function () {
return function(savings, requirement) {
var filterKey = Object.keys(requirement)[0];
var filterVal = requirement[filterKey];
var filtered = [];
if(filterVal !== undefined && filterVal !== ''){
angular.forEach(savings, function(saving) {
var today = new Date();
var date = new Date(saving.created.$date);
var diff = today - date;
diff = diff / (1000*60*60);
if(diff < filterVal) {
filtered.push(saving);
}
});
alert(filtered.length);
return filtered;
}
return savings;
};
});
Ive tried implement the answer below but it doesnt return any results.
Screenshot of resource.
I'll save you some time.. here is your filter.
app.filter('lessThan', function () {
return function(items, requirement) {
var filterKey = Object.keys(requirement)[0];
var filterVal = requirement[filterKey];
var filtered = [];
if(filterVal !== undefined && filterVal !== ''){
angular.forEach(items, function(item) {
var today = new Date();
var date = new Date(item.created)
var diff = today - date;
diff = diff / (1000*60*60)
if(diff < filterVal) {
filtered.push(item);
}
});
return filtered;
}
return items;
};
});
And call it like:
<div ng-repeat="item in items | lessThan: {'created':24}">
Here is a plunker.
EDIT: Based on the screenshot created property looks more like this:
"created": "2016-01-29T22:05:03.574Z"
I've edited the filter for this model
Related
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;
This is firebase structure for categories2.
and this is for subcategories2.
To display data on screen I want $scope.Categories [] to be filled in this format.
[{
"id": "1",
"display_with": "7",
"image": "/images/salt_sugar.png",
"name": "Salt & Sugar",
"subcategories": [{
"scid": "1",
"scname": "Sugar Products"
},
{
"scid": "5",
"scname": "Tea"
}
]
},
.
.
.
.
]
Logic for filling $scope.Categories [].
$scope.Categories = [];
var categoriesRef = firebase.database().ref('categories2');
categoriesRef.on('value', function(snapshot) {
$scope.Categories = [];
var recvCategories = [];
recvCategories = snapshot.val();
for (var j=0; j<recvCategories.length; ++j){
var category = recvCategories[j];
//alert (category);
if (category != undefined){
var category_modified = {};
category_modified.id = category.id;
category_modified.display_with = category.display_with;
category_modified.name = category.name;
category_modified.image = category.image;
var subcategories = [];
for(var key in category.subcategories) {
var subcategoriesRef = firebase.database().ref('subcategories2/' + key);
subcategoriesRef.on('value', function(snapshot2) {
subcategories.push(snapshot2.val());
});
}
category_modified.subcategories = subcategories;
$scope.Categories.push(category_modified);
}
}
$scope.$apply();
});
As soon as data is available in want to display it on screen. so i am using $scope.$apply();
The problem is data is not displaying properly. but once i go to other controller and come back to same controller, everything displays as expected.
Why subcategories information is not adding up properly in $scope.Categories[]
I just modified your fiddle. just check the following link https://jsfiddle.net/py3ofkyc/8/
function myFunction() {
var subcategories = [];
var subcategoriesRef = firebase.database().ref('subcategories2');
subcategoriesRef.on('value', function(snapshot2) {
subcategories = snapshot2.val();
var Categories = [];
var categoriesRef = firebase.database().ref('categories2');
categoriesRef.on('value', function(snapshot) {
var Categories = [];
var recvCategories = [];
recvCategories = snapshot.val();
_(recvCategories).forEach(function(value) {
var category = value;
if (category != undefined){
var category_modified = {};
category_modified.id = category.id;
category_modified.display_with = category.display_with;
category_modified.name = category.name;
category_modified.image = category.image;
var _subcategories = [];
for(var key in category.subcategories) {
var data = _.filter(subcategories, { 'scid': key });
_subcategories.push(data[0]);
}
category_modified.subcategories = _subcategories;
Categories.push(category_modified);
}
});
console.log(Categories);
});
});
}`
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
I am currently working on an app using firebase and angularJS (ionic). Basically this is a car management app, so you have people sharing their cars with others. I tried to structure the data as flat as possible to be efficient. My issue here is that if without problem I can display the list of the car_id of the different cars shared with the logged user, I can't find a way to display the list of cars shared with the user displaying the year and the model.
Thank you in advance for your help !
{
"rules": {
"users": {
".write": true,
"$uid": {
".read": "auth != null && auth.uid == $uid"
},
"cars": {
"car_id":true,
"role":true // Owner, borower...
}
},
"cars": {
"car_id":true,
"model":true,
"year":true
}
}
}
carapp.controller("carsController", function($scope, $firebaseObject, $ionicPopup, $ionicHistory) {
$ionicHistory.clearHistory();
$scope.list = function() {
frbAuth = frb.getAuth();
if(frbAuth) {
var userObject = $firebaseObject(frb.child("users/" + frbAuth.uid));
userObject.$bindTo($scope, "user");
$scope.cars = frb.child("cars");
}}
$scope.createCar = function() {
$ionicPopup.prompt({
model: 'Create a new car',
inputType: 'text'
})
.then(function(result) {
if(result !== "") {
var newCar = $scope.cars.push({
model: result
})
var newCarId = newCar.key();
$scope.user.cars.push({car_id: newCarId, role: "owner" });
} else {
console.log("Action not completed");
}
});
}
});
<div class="list">
<a ng-repeat="car in user.cars" >
<h2>{{car.car_id}}</h2> ----> works fine !
<h2>{{car.model}}</h2> ----> How to get this working ?
<h2>{{car.year}}</h2> ----> How to get this working ?
</a>
</div>
In the users/ path, begin by storing the list of cars by index, instead of in an array. So your structure would be:
{
"users": {
"kato": {
"cars": {
"DeLorean": true
}
}
},
"cars": {
"DeLorean": {
model: "DeLorean",
year: "1975"
}
}
}
To join this using AngularFire, you have several approaches available. An AngularFire-only solution might look like this, taking advantage of $extend:
app.factory('CarsByUser', function($firebaseArray) {
return $firebaseArray.$extend({
$$added: function(snap) {
return new Car(snap);
},
$$updated: function(snap) {
// nothing to do here; the value of the index is not used
},
$$removed: function(snap) {
this.$getRecord(snap.key()).destroy();
},
// these could be implemented in a manner consistent with the
// use case and above code, for simplicity, they are disabled here
$add: readOnly,
$save: readOnly
});
var carsRef = new Firebase(...).child('cars');
function Car(snap) {
// create a reference to the data for a specific car
this.$id = snap.key();
this.ref = carsRef.child(this.$id);
// listen for changes to the data
this.ref.on('value', this.updated, this);
}
Car.prototype.updated = function(snap) {
this.model = data.model;
this.year = data.year;
}
Car.prototype.destroy = function() {
this.ref.off('value', this.meta, this);
};
function readOnly() { throw new Error('This is a read only list'); }
});
app.controller('...', function($scope, CarsByUser, authData) {
// authenticate first, preferably with resolve
var ref = new Firebase(...).child(authData.uid);
$scope.cars = CarsByUser($scope);
});
For a more sophisticated and elegant approach, one could utilize NormalizedCollection and pass that ref into the AngularFire array:
app.controller('...', function($scope, $firebaseArray) {
var ref = new Firebase(...);
var nc = new Firebase.util.NormalizedCollection(
ref.child('users/' + authData.uid),
ref.child('cars')
)
.select('cars.model', 'cars.year')
.ref();
$scope.cars = $firebaseArray(nc);
});
I always manage pagination with angular
retrieve all the data from the server
and cache it client side (simply put it in a service)
now I have to cope with quite lot of data
ie 10000/100000.
I'm wondering if can get into trouble
using the same method.
Imo passing parameter to server like
page search it's very annoying for a good
user experience.
UPDATE (for the point in the comment)
So a possible way to go
could be get from the server
like 1000 items at once if the user go too close
to the offset (ie it's on the 800 items)
retrieve the next 1000 items from the server
merge cache and so on
it's quite strange not even ng-grid manage pagination
sending parameters to the server
UPDATE
I ended up like:
(function(window, angular, undefined) {
'use strict';
angular.module('my.modal.stream',[])
.provider('Stream', function() {
var apiBaseUrl = null;
this.setBaseUrl = function(url) {
apiBaseUrl = url;
};
this.$get = function($http,$q) {
return {
get: function(id) {
if(apiBaseUrl===null){
throw new Error('You should set a base api url');
}
if(typeof id !== 'number'){
throw new Error('Only integer is allowed');
}
if(id < 1){
throw new Error('Only integer greater than 1 is allowed');
}
var url = apiBaseUrl + '/' + id;
var deferred = $q.defer();
$http.get(url)
.success(function (response) {
deferred.resolve(response);
})
.error(function(data, status, headers, config) {
deferred.reject([]);
});
return deferred.promise;
}
};
};
});
})(window, angular);
(function(window, angular, undefined) {
'use strict';
angular.module('my.mod.pagination',['my.mod.stream'])
.factory('Paginator', function(Stream) {
return function(pageSize) {
var cache =[];
var staticCache =[];
var hasNext = false;
var currentOffset= 0;
var numOfItemsXpage = pageSize;
var numOfItems = 0;
var totPages = 0;
var currentPage = 1;
var end = 0;
var start = 0;
var chunk = 0;
var currentChunk = 1;
var offSetLimit = 0;
var load = function() {
Stream.get(currentChunk).then(function(response){
staticCache = _.union(staticCache,response.data);
cache = _.union(cache,response.data);
chunk = response.chunk;
loadFromCache();
});
};
var loadFromCache= function() {
numOfItems = cache.length;
offSetLimit = (currentPage*numOfItemsXpage)+numOfItemsXpage;
if(offSetLimit > numOfItems){
currentChunk++;
load();
}
hasNext = numOfItems > numOfItemsXpage;
totPages = Math.ceil(numOfItems/numOfItemsXpage);
paginator.items = cache.slice(currentOffset, numOfItemsXpage*currentPage);
start = totPages + 1;
end = totPages+1;
hasNext = numOfItems > (currentPage * numOfItemsXpage);
};
var paginator = {
items : [],
notFilterLabel: '',
hasNext: function() {
return hasNext;
},
hasPrevious: function() {
return currentOffset !== 0;
},
hasFirst: function() {
return currentPage !== 1;
},
hasLast: function() {
return totPages > 2 && currentPage!==totPages;
},
next: function() {
if (this.hasNext()) {
currentPage++;
currentOffset += numOfItemsXpage;
loadFromCache();
}
},
previous: function() {
if(this.hasPrevious()) {
currentPage--;
currentOffset -= numOfItemsXpage;
loadFromCache();
}
},
toPageId:function(num){
currentPage=num;
currentOffset= (num-1) * numOfItemsXpage;
loadFromCache();
},
first:function(){
this.toPageId(1);
},
last:function(){
this.toPageId(totPages);
},
getNumOfItems : function(){
return numOfItems;
},
getCurrentPage: function() {
return currentPage;
},
getEnd: function() {
return end;
},
getStart: function() {
return start;
},
getTotPages: function() {
return totPages;
},
getNumOfItemsXpage:function(){
return numOfItemsXpage;
},
search:function(str){
if(str===this.notFilterLabel){
if(angular.equals(staticCache, cache)){
return;
}
cache = staticCache;
}
else{
cache = staticCache;
cache = _.filter(cache, function(item){ return item.type == str; });
}
currentPage = 1;
currentOffset= 0;
loadFromCache();
}
};
load();
return paginator;
}
});
})(window, angular);
server side with laravel (All the items are cached)
public function tag($page)
{
$service = new ApiTagService(new ApiTagModel());
$items = $service->all();
$numOfItems = count($items);
if($numOfItems > 0){
$length = self::CHUNK;
if($length > $numOfItems){
$length = $numOfItems;
}
$numOfPages = ceil($numOfItems/$length);
if($page > $numOfPages){
$page = $numOfPages;
}
$offSet = ($page - 1) * $length;
$chunk = array_slice($items, $offSet, $length);
return Response::json(array(
'status'=>200,
'pages'=>$numOfPages,
'chunk'=>$length,
'data'=> $chunk
),200);
}
return Response::json(array(
'status'=>200,
'data'=> array()
),200);
}
The only trouble by now is managing filter
I've no idea how to treat filtering :(