Infinite Scrolling reloads page, Ionic - angularjs

What is happening is that when I reach the bottom of the page, it refreshes and loads the new data, however it doesn't show the data for the previous and current page.
For example it looks like this:
1
2
3
4
* end of page, refreshes page*
5
6
7
8
My function in my controller:
var i = 0;
$scope.result = [];
$scope.noMoreItemsAvailable = false;
$scope.loadMore = function() {
if (i < 4) {
$http.get(url.recommended + i).success(function(response) {
i++;
$scope.result = $scope.result.push(response);
console.log(response);
$timeout(function() {
$scope.result = response
});
$scope.$broadcast('scroll.infiniteScrollComplete');
});
} else {
$scope.noMoreItemsAvailable = true;
}
}
HTML:
<div class="item item-text-wrap" ng-click="post($event,res)" ng-repeat="res in result" ng-controller="recommendedJobsCtrl" ui-sref="tabs.jobDetails">
<ul>
<li id="jobTitle">{{res.title }}</li>
</ul>
</div>
<ion-infinite-scroll ng-if="!noMoreItemsAvailable" on-infinite="loadMore()" distance="1%"></ion-infinite-scroll>

Well, there are 2 main problems:
You're attributing the value of the push for your array. You shouldn't do this, you just have to do this:
$scope.result.push(response);
You should remove this timeout because it's overriding what you already have:
$timeout(function() {
$scope.result = response
});
By the way, I'd recommend you to create a factory to prevent problems with async data.
You could do something like this:
angular
.module('app', [])
.controller("MainCtrl", MainCtrl)
.factory("ItemsFactory", ItemsFactory);
ItemsFactory.$inject = ['$http'];
function ItemsFactory($http) {
var factory = {
getPages: getPages
};
return factory;
function getPages(url) {
return $http.get(url);
}
}
Then, in your controller:
MainCtrl.$inject = ['$scope', 'ItemsFactory'];
function MainCtrl($scope, ItemsFactory) {
var url = 'https://www.google.com';
function getResponse(response) {
$scope.result.push(response.data);
}
function getError(response) {
console.log(response);
}
ItemsFactory.getPages(url)
.then(getResponse);
.catch(getError);
}
Please, note: I also recommend you to change the way that you're retrieving your items from your back-end. It isn't a good way to retrieve the elements 1 by 1. The correct in your case is to retrieve all the four items at once and treat them in controller.

Your timeout is causing the $scope.result to be overwritten by the response.
Just remove this and it should append the response to the result
REMOVE THIS
$timeout(function ()
{
$scope.result=response
});

Related

Adding auto refresh after a particular interval (5 seconds) in angular js

I have a page in which which has multiple tabs. I want to add the feature that the tab is reloaded automatically after a fixed duration. I have the following:
<uib-tab index="$index + 1" ng-repeat="environmentRegionTab in ctrl.environmentRegionTabs"
heading="{{environmentRegionTab.environmentRegionName}}"
select="ctrl.onEnvironmentRegionSelect(environmentRegionTab.id);">
<div class="panel-body tab-content">
<div class="alert alert-success" ng-show="ctrl.deployStatus[ctrl.environmentRegion.name].show">
<strong>Launched deployment with execution id
{{ctrl.deployStatus[ctrl.environmentRegion.name].id}}</strong>
</div>
...................
And the following controller:
export function ServiceDetailController(ecsServiceResponse, teamListResponse, productListResponse, businessSubOwnerListResponse, serviceInstancesResponse, businessOwnerListResponse, EcsService, SecretsService, $location, $stateParams, $uibModal, $scope, $state, $window) {
'ngInject';
var self = this;
var serviceInstanceId;
self.ecsAuthControl = {};
self.initialize = _initialize;
self.clearMessages = _clearMessages();
self.onEnvironmentRegionSelect = _onEnvironmentRegionSelect;
$scope.reloadRoute = function() {
$state.reload();
};
function _onEnvironmentRegionSelect(serviceInstanceId) {
self.selectedserviceInstanceId = serviceInstanceId;
if (serviceInstanceId) {
$location.search('serviceInstanceId', serviceInstanceId);
_loadEnvironmentRegion();
} else {
$location.search('serviceInstanceId', null);
_loadSummary();
}
}
}
I am not able to understand how to add the fixed time duration? I also would like to show a counter ticking down from 5 to 0 after which the page is reloaded. How can I do it? I declared the reload function but I am not able to figure out how to add a fixed timer? Thanks!
Make use of $interval service in angularjs:
$interval(function () {
$scope.reloadRoute();
}, 5000);
(make sure to pass $interval as a dependency to controller)
Example Plunker
Here is one of the safest way through which you can achieve the functionality.
Function which does the refresh:-
var poll = function() {
console.log("polling");
$scope.doRefresh(); // Your refresh logic
};
Call the poll from StartPollar:
var startPoller = function() {
if (angular.isDefined(stop)) {
stopPoller();
}
stop = $interval(poll, $scope.intervalTime); //$scope.intervalTime : refresh interval time
};
If you want to Stop it:
var stopPoller = function() {
if (angular.isDefined(stop)) {
$interval.cancel(stop);
stop = undefined;
console.log("cancelled poller operation");
} else {
console.log("do nothing");
}
};

Angular binding not working properly with ngInfiniteScroll

Basically I have a timeline with posts that is a $firebaseArray and any change to this array is getting binded properly. But when I want to bind any other data it only binds when ngInfiniteScroll is trying to retrieve more data from firebase, so only when I scroll down.
In the code bellow I'm calling {{getMoreDetails()}} and this data is binded when the first set of data is being retrieved with ngInfiniteScroll but as soon as it is loaded the bind breaks and only binds again when scrolling.
My concerns here are:
Was ngInfiniteScroll designed to work this way?
Is there any workaround in this scenario?
Stack:
"firebase": "2.4.2","angularfire": "~1.2.0","firebase-util": "0.2.5","ngInfiniteScroll": "1.2.2"
timeline.html
<div ng-controller="TimelineController">
<section class="entrys main-content" infinite-scroll="posts.scroll.next(3)" infinite-scroll-distance="0.3">
<div class="inner">
<div ng-repeat="post in filteredPostsResults = (posts | filter:postIdFilter)">
<article class="entry">
<img ng-if="post.sourceType=='IMAGE'" data-ng-src="{{getPostData(post)}}"/>
<div class="entry-info">
<h3><div ng-bind-html="post.description | emoticons"></div></h3>
<small>posted on <time>{{getDateInFormat(post.createdAt)}}</time></small>
{{getMoreDetails()}}
</div>
</article>
</div>
</div>
</section>
</div>
timeline.js
(function (angular) {
"use strict";
var timeline = angular.module('myApp.user.timeline', ['firebase', 'firebase.utils', 'firebase.auth', 'ngRoute', 'myApp.user.timelineService']);
timeline.controller('TimelineController', [ '$scope', '$routeParams', 'TimelineService', '$publisherServices', '$securityProperties', function ($scope, $routeParams, TimelineService, $publisherServices, $securityProperties) {
if (!$scope.posts){
$scope.posts = TimelineService.getPosts($routeParams.userId);
}
$scope.posts.$loaded(function(result) {
$scope.isPostsLoaded = true;
});
$scope.getMoreDetails = function() {
console.log("LOGGED ONLY WHEN SCROLLING");
return $publisherServices.getDetails();
};
$scope.getPostData = function(post) {
if (!post.dataUrl){
post.dataUrl = $publisherServices.getAwsFileUrl(post.fileName);
}
return post.dataUrl;
};
$scope.postIdFilter = function(post) {
if ($routeParams.postId){
if (post.$id == $routeParams.postId) return post;
} else { return post; }
};
$scope.getDateInFormat = function(timestamp){
var date = new Date();
date.setTime(timestamp);
return date;
};
}]);
})(angular);
timelineService.js
(function (angular) {
"use strict";
var timelineService = angular.module('myApp.user.timelineService', []);
timelineService.service('TimelineService', ['$routeParams', 'FBURL', '$firebaseArray', function ($routeParams, FBURL, $firebaseArray) {
var posts;
var currentUserIdPosts;
var postsRef;
var self = {
getPosts: function(userId){
if (!posts || userId != currentUserIdPosts){
currentUserIdPosts = userId;
postsRef = new Firebase(FBURL).child("posts").child(userId);
var scrollRef = new Firebase.util.Scroll(postsRef, "createdAtDesc");
posts = $firebaseArray(scrollRef);
posts.scroll = scrollRef.scroll;
}
return posts;
}
}
return self;
}]);
})(angular);
I am assuming that you want the post details updated when the data from your Firebase changes.
When Firebase changes are applied to your scope, it seems that it doesn't trigger a digest cycle, so you probably need to do it manually every time you get updates from Firebase.
Take a look at $$updated in $firebaseArray.$extend (see docs).
// now let's create a synchronized array factory that uses our Widget
app.factory("WidgetFactory", function($firebaseArray, Widget) {
return $firebaseArray.$extend({
// override the update behavior to call Widget.update()
$$updated: function(snap) {
// we need to return true/false here or $watch listeners will not get triggered
// luckily, our Widget.prototype.update() method already returns a boolean if
// anything has changed
return this.$getRecord(snap.key()).update(snap);
}
});
});
I hope this helps.

how to connect 2 objects in ionic via backand

i need a bit of help to my ionic project. so i want to connect 2 objects in ionic, so that i can display the value of and object that has data from the other object.
<ion-list class="list-inset">
<ion-item class="item-text-wrap" ng-repeat='item in todos| filter:firma'>
<h2>{{item.company_name}}</h2>
</ion-item>
<ion-item class="item-text-wrap" ng-repeat='item in todos2 | filter:{ idcompany:com_id } '>
<h2>ponedeljek {{item.time_mon_start}}-{{item.time_mon_end}}</h2>
<h2>torek {{item.time_tue_start}}-{{item.time_tue_end}}</h2>
<h2>sreda {{item.time_wed_start}}-{{item.time_wed_end}}</h2>
<h2>Ĩetrtek {{item.time_thu_start}}-{{item.time_thu_end}}</h2>
<h2>petek {{item.time_fri_start}}-{{item.time_fri_end}}</h2>
<h2>sobota {{item.time_sat_start}}-{{item.time_sat_end}}</h2>
<h2>nedelja {{item.time_sun_start}}-{{item.time_sun_end}}</h2>
</ion-item>
this is what i want to display for the current company that i click on, but it shows all the times not only one that i want.
.controller('AppCtrl', function($scope, TodoService, cas, $state) {
$scope.todos = [];
$scope.todos2 = [];
function getAllTodos() {
TodoService.getTodos().then(function (result) {
$scope.todos = result.data.data;
$scope.firma = $state.params.aid;
});
}
getAllTodos();
function getalltimes() {
cas.getcompany().then(function (result) {
$scope.todos2 = result.data.data;
});
}
getalltimes();
})
.service('TodoService', function ($http, Backand, $state) {
var baseUrl = '/1/objects/';
var objectName = 'companies/';
function getUrl() {
return Backand.getApiUrl() + baseUrl + objectName;
}
function getUrlForId(id) {
return getUrl() + id;
}
getTodos = function () {
return $http.get(getUrl());
};
return {
getTodos: getTodos
}
})
.service('cas', function ($http, Backand, $state) {
var baseUrl = '/1/objects/';
var time = 'companies_timetable/';
function getUrl2() {
return Backand.getApiUrl() + baseUrl + time;
}
getcompany = function () {
return $http.get(getUrl2());
};
return {
getcompany: getcompany
}
})
this is now my app.js file and my connection to the backand service. this is working fine.
this are the companys from object 1
and this are the times showing
so when you click on the companys it should show the time for it. but here it shows all times that are in the object. i should show only one for the one company
i was trying to give all objects in one array (todos). but didn't worked rlly well. so please i need some help. if you need some more code or somthing just say it :).
Your second filter is wrong.
Simplest way to fix it is to call a function in $scope.
Change your filter like this:
<ion-item class="item-text-wrap" ng-repeat='item in todos2 | filter: isCurrentFirma '>
Then add a function in your controller:
$scope.isCurrentFirma = function(item){
// here check if item is equal to firma
// code like this:
return item.idcompany === $scope.firma.com_id
}

Initialise AngularJS service - factory on the document load

Sorry for a very stupid question but I just started working with AngularJS and OnsenUI.
I have got a service to get a data from SQLite:
module.factory('$update', function () {
var update = {};
db.transaction(function (tx) {
tx.executeSql('SELECT * FROM event_updates', [], function (tx, results) {
var rows = results.rows;
update.items = [];
if (!rows.length) {} else {
for (var index = 0; index < rows.length; index++) {
update.items.push({
"title": rows.item(index).title,
"date": rows.item(index).date,
"desc": rows.item(index).desc
});
}
}
}, function (error) {
console.log(error);
});
});
return update;
});
And a controller which is using the data:
module.controller('UpdatesController', function ($scope, $update) {
$scope.items = $update.items;
});
As soon as my page is loaded the content is not displayed and I need to click twice to call a page with the code below to see the content:
<ons-list ng-controller="UpdatesController">
<ons-list-item modifier="chevron" class="list-item-container" ng-repeat="item in items" ng-click="showUpdate($index)">
<div class="list-item-left">
</div>
<div class="list-item-right">
<div class="list-item-content">
<div class="name">{{item.title}}</div> <span class="desc">{{item.desc}}</span>
</div>
</div>
</ons-list-item>
</ons-list>
Can anybody help how can I initialise the controller as soon as page is loaded with all content. Sorry if it is a stupid question but I am really struggling. Appreciate your help a lot.
You could store the result of the request in the factory and retrieve those instead.
module.factory('$update', function () {
var update = {};
var requestValues = function(){ // store the results of the request in 'update'
// Your db.transaction function here
}
var getUpdates = function(){ // retrieve the values from 'update'
return update;
}
return{
requestValues : requestValues,
getUpdates : getUpdates
}
});
And then in you controller:
module.controller('UpdatesController', function ($scope, $update) {
$update.requestValues();
$scope.items = $update.getUpdates();
});
You could then get the values from anywhere in you solution (by using $update.getUpdates) without having to make an extra http request.

Angular call service on asynchronous data

I have a service that make some calls to retrieve data to use in my app. After I've loaded data, I need to call another service to make some operations on my data. The problem is that second service will not have access to the data of the first service.
I've made a plunker: plunkr
First service
app.factory('Report', ['$http', function($http,$q){
var Authors = {
reports : [],
requests :[{'url':'data.json','response':'first'},
{'url':'data2.json','response':'second'},
{'url':'data3.json','response':'third'}]
};
Authors.getReport = function(target, source, response, callback) {
return $http({ url:source,
method:"GET",
//params:{url : target}
}).success(function(result) {
angular.extend(Authors.reports, result)
callback(result)
}
).error(function(error){
})
}
Authors.startQueue = function (target,callback) {
var promises = [];
this.requests.forEach(function (obj, i) {
console.log(obj.url)
promises.push(Authors.getReport(target, obj.url, obj.response, function(response,reports){
callback(obj.response,Authors.reports)
}));
});
}
return Authors;
}])
Second service
app.service('keyService', function(){
this.analyze = function(value) {
console.log(value)
return value.length
}
});
Conroller
In the controller I try something like:
$scope.result = Report.startQueue('http://www.prestitiinpdap.it', function (response,reports,keyService) {
$scope.progressBar +=33;
$scope.progress = response;
$scope.report = reports;
});
$scope.test = function(value){
keyService.analyze($scope.report.about);
}
I think this is what you are going for? Essentially, you want to call the second service after the first succeeds. There are other ways of doing this, but based on your example this is the simplest.
http://plnkr.co/edit/J2fGXR?p=preview
$scope.result = Report.startQueue('http://www.prestitiinpdap.it', function (response,reports) {
$scope.progressBar +=33;
$scope.progress = response;
$scope.report = reports;
$scope.test($scope.report.about); //added this line
});
$scope.test = function(value){
$scope.example = keyService.analyze(value); //changed this line to assign property "example"
}
<body ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
<p>Progress notification : {{progress}}!</p>
<div ng-show="show">
<progress percent="progressBar" class="progress-striped active"></progress>
</div>
<pre>{{report}}</pre>
<pre>{{report.about}}</pre>
{{example}} <!-- changed this binding -->
</body>

Resources