AngularJS - Append to a model with a $resource - angularjs

I have this service:
factory('Post', function($resource) {
return $resource('/api/post.json', {},
{
query: {method:'GET', isArray: false}
}
);
})
And I have this controller:
function PostsCtrl($scope, Post) {
// init
$scope.page = 0;
$scope.page_has_next = true;
$scope.loadMore = function() {
if($scope.page_has_next) {
$scope.posts = Post.query({page: ++$scope.page},
function(data) {
$scope.page_has_next = data.has_next;
}
);
}
}
$scope.loadMore();
}
This works just fine, each time loadMore() is executed the model gets updated with the next page until there are no more pages. However, I want to append the new set of posts to the current model instead of replacing it, how can I do that?

Assuming that posts is a array:
$scope.posts = $scope.posts.concat(Post.query({page: ++$scope.page})
This will only work if the new posts has no duplicates with the old posts. If there are duplicates, you have to traverse the array and push only new posts.

Related

Ionic Pagination starting

I am trying to create a pagination feature but I feel stuck. I am not sure if I am on the right track...
in my view, I have an ng-repeat=" res in result", and at the end of the page i placed the following:
<ion-infinite-scroll on-infinite="loadMore()" distance="1%"></ion-infinite-scroll>
then in the controller, i wrote this:
var i=1;
$http.get( "http://website/search/"+i).success(function(response){
i++;
$scope.result=(response)
});
}
each pages returns a json containing 15 elements. What I want to do is when i reach the end, I want to load the next 15 in the result to be displayed.
You have to fetch next 15 item in loadMore function in controller as you write on-infinite="loadMore()" in ion-infinite-scroll
Write function as follow in your controller
$scope.result = [];
var i=1;
$scope.loadMore = function(){
$http.get( "http://website/search/"+i).success(function(response){
i++;
$scope.result.push(response);
});
}
Check Example
Hears how I have implemented infinite-scroll in my app
<ion-infinite-scroll ng-if="!loadMorePeople" on-infinite="loadPeople()" distance="1%"></ion-infinite-scroll>
loadPeople() loads all the scrolled data, it's code is bellow
$scope.loadMorePeople=false;
$scope.loadPeople = function() {
if($scope.peoples != null){
$http({
method: "get",
url: baseUrl+"company-members?page="+$scope.pagePeople,
withCredentials: true,
headers: {
'Accept' : 'application/json, text/plain, */*',
'Authorization' : ''+window.localStorage.getItem("token_type")+' '+window.localStorage.getItem("token")
}
})
.success(function(data) {
if(data.length > 0){
var newPeople = data;
$scope.temp = $scope.peoples.concat(newPeople);
$scope.peoples = arrayUnique($scope.temp, 'id');
function arrayUnique(collection, keyname) {
var output = [],
keys = [];
angular.forEach(collection, function(item) {
var key = item[keyname];
if(keys.indexOf(key) === -1) {
keys.push(key);
output.push(item);
}
});
return output;
};
++$scope.pagePeople;
$scope.$broadcast("scroll.infiniteScrollComplete");
}else{
$scope.loadMorePeople=true;
$scope.$broadcast("scroll.infiniteScrollComplete");
}
})
.error(function(data, status) {
});
}
$scope.$broadcast("scroll.infiniteScrollComplete");
};
I too had the same problem as you for some reason .push() was not working so I did this workaround.
I took the data checked if it's not null in if(data.length > 0){} and then used .concat(newPeople) to merge them and finally used arrayUnique($scope.temp, 'id') to make sure that there is no duplicate entity.
It's also a good idea to use ng-if="!loadMorePeople" it help to stop the call if there is no data left to fetch else the call will continously go on.
I hope this solves your problem. Let me know if you need any help :D

$scope is not updated after ngResource POSTed new item successfully

I have run into this issue in my app several times. I have a fun ngResource resources that I attach to $scope as $scope.jogasok = Jogas.query();, and I create a new resource in the same scope by calling something like
$scope.addJogas = function (jogas) {
$scope.isDisabled = true;
var j = new Jogas(jogas);
j.$save(function (value) {
$scope.isDisabled = false;
}, httpErrorHandler);
};
where Jogas is an ngResource
.factory('Jogas', function ($resource) {
var Jogas = $resource('/jogasok/:id/:action', {
'id': '#_id',
'action': '#action'
}, {
'ujBerlet': {'method': 'POST', 'params': {'action': 'ujberlet'}}
});
return Jogas;
})
The POST call is successful, thus reloading the page shows the new item in $scope.jogasok, but the new item is not shown if I don't reload.
Have can I get $scope.jogasok reloaded/extended automatically when $save has finished?
I've figured out my own dumbness concerning this question.
$scope.jogasok is an Array, thus its value will not change without changing it.
The most basic solution is to reload $scope.jogasok in the success handler:
$scope.addJogas = function (jogas) {
$scope.isDisabled = true;
var j = new Jogas(jogas);
j.$save(function (value) {
$scope.jogasok = Jogas.query();
$scope.isDisabled = false;
}, httpErrorHandler);
};

AngularJS service storing and updating data

I have a simple app that shows a list of people each with a link to an edit controller. The edit controller gets the person by id. Once the edit form has been submitted, the page is redirected back to the person list.
I have a method to update the service data in the callback after the server saves the person. The method I use does in fact work, however, I wasn't sure if there was a better way to achieve this. After much searching I haven't found a concrete answer so I wanted to reach out to the AngularJS community here for help.
Here is a fiddle: http://jsfiddle.net/7bGEG/
var app = angular.module('peopleApp',[]);
app.controller('ListCtrl',function($scope,People) {
People.getList().then(function(response) {
$scope.list = response; // show list of people with a link to new route to edit
});
});
app.controller('EditCtrl',function($scope,$location,$routeParams,People) {
// edit route so get person by id
People.getById($routeParams.id).then(function(response) {
$scope.person = response.person;
});
// submit save person form and send back to person list
$scope.savePerson = function() {
People.savePerson($scope.person).then(function(response) {
$location.path('/');
});
}
});
app.factory('People',function($http,$q) {
var people = [];
var people_q = $q.defer();
$http.get(url).then(function(response) {
people = response.data;
people_q.resolve(people);
});
return {
getList: function() {
return people_q.promise;
},
getById: function(id) {
return $http.get(url).then(function(response) {
return response.data;
});
},
savePerson: function(person) {
return $http.post(url).then(function(response) {
// find person in person array and remove them
for (i=0; i < people.length; i++) {
if (people[i].person_id == person.person_id) {
people.splice(i,1);
break;
}
}
// add new person data
people.push(response.data);
return response.data;
});
}
}
});

AngularJS scope refresh on post to API through restangular

I have a controller which loads data via Restangular like so:
var oneTopic = Restangular.one('topics', topic.id);
oneTopic.get({}, {"Authorization" : localStorageService.get('***')}).then(function(topic) {
topic.getList('comments', {}, {"Authorization" : localStorageService.get('***')}).then(function(comments){
$scope.comments = comments;
//console.log($scope.comments);
});
});
And then a function which posts a new comment and one that deletes a comment.
$scope.delComment = function(comment_id, author_id){
var comment = Restangular.one('comments', comment_id);
comment.remove({author_id: author_id}, {"Authorization" : localStorageService.get('***')}).then(function(){
// need to perform refresh here
});
};
$scope.postComment = function(mood) {
$scope.commentData.mood = mood;
comments.post($scope.commentData, {}, {"Authorization" : localStorageService.get('***')}).then(function(response){
// need to perform refresh here
}, function(response){
$scope.error = response.data.message;
})
};
How would I refresh the comments scope without reloading the page? The data is being populated in the HTML with an
<div ng-repeat="comment in comments">
Modify the existing array referenced by $scope.comments and the data binding will take care of it.
For example:
$scope.delComment = function(comment_id, author_id) {
var comment = Restangular.one('comments', comment_id);
comment.remove({ author_id: author_id }, { "Authorization": localStorageService.get('***')
}).then(function() {
// Some remove-from-array implementation, for example:
var c = $scope.comments;
for(var i = 0, l = c.length; i < l; i++) {
if (c[i].comment_id === comment_id) {
c = c.splice(i, 1);
break;
}
}
});
};

Angularjs how to stop infinity scroll when server has no more data to send

Based on THIS example which I have modified with an Ajax request to get the data Im struggling to find a way to stop it when the server has no more data to send.
I have tried to add a boolean variable in a service, and a $watch method in the directive but it is not working.
Is there a simple way to to achieve that ?
This is not my code but if there is no easy answer I can post my code with the changes I have done.
thanks for your help.
<div id="fixed" when-scrolled="loadMore()">
<ul>
<li ng-repeat="i in items">{{i.id}}</li>
</ul>
</div>
function Main($scope) {
$scope.data = { comments : [] }
$scope.loadMore = function(){
$http({
url: '/comment/next',
method: "POST"
})
.success(function(data){
for(var i=0; i<data.length; i++){
$scope.data.comments.push(data[i]);
}
});
}
}
angular.module('scroll', []).directive('whenScrolled', function() {
return function(scope, elm, attr) {
var raw = elm[0];
elm.bind('scroll', function() {
if (raw.scrollTop + raw.offsetHeight >= raw.scrollHeight) {
scope.$apply(attr.whenScrolled);
}
});
};
});
I can only guess as to a solution without seeing more of your code (specifically what is returned by $http results), but I believe this sort of thing could work, depending on the structure of a comment object.
function Main($scope) {
$scope.data = { comments : [] }
$scope.scrollComplete = false;
$scope.loadMore = function(){
if($scope.scrollComplete || $scope.loading) { return; }
$scope.loading = true;
$http({
url: '/comment/next',
method: "POST"
})
.success(function(data){
for(var i=0; i<data.length; i++){
var totalComments = $scope.data.comments.length;
if($scope.data.comments[totalComments - 1].someID === data[i].someID){
$scope.scrollComplete = true;
}else{
$scope.data.comments.push(data[i]);
}
}
$scope.loading = false;
}).error(function(){ $scope.loading = false });
}
}
Just bear in mind that a solution like this isn't really elegant. What I like to do is allow an item ID to be passed to the API (i.e. your /comment/next), and treat that as the last grabbed item. So the API will only give me back everything after that. Using that method, you would simply have to pass the last comment ID to the API.

Resources