angularjs - $http post reqest in queue one by one - angularjs

I have hundred rows in my view. I would like to process all those rows one by one.
Every row has status
Not Complete (by default)
Complete
Processing
I would like to change status of each row before and after finish processing in controller.
Before finishing I would like to change status to processing and after finishing, I like to change complete.
<tr ng-repeat="item in pagedItems[currentPage] | orderBy:sortingOrder:reverse ">
<td>{{item.id}}</td>
<td>{{item.fname}}</td>
<td>{{item.lname}}</td>
<td>
<span ng-class="class{{item.id}}"></span>
</td>
</tr>
in controller I have
$scope.startSending = function() {
$scope.filteredItems.forEach(function(entry) {
// Throwing Error! How can dynamically get value of scope variable
$scope.'class'+entry.id = 'icon-eye-open';
});
};
Please advise how can I get value of dynamical named variable from $scope above in controller.
I would like to update my database as well, If I add $http in foreach loop.
$http.post('/someUrl', data).success(successCallback);
it will send all 100 requests all together. Can I execute each request one after another in queue?
I want to send request in queue, it should not send second request before completion of first request etc...
any idea?
Thanks

With respect to Please advise how can I get value of dynamical named variable from $scope above in controller. the answer is Javascript and not AngularJS related. Just do:
$scope['class' + entry.id] = 'icon-eye-open';
With respect to queueing the $http requests, you want to check out the various asynchronous flow control solutions. I've used in a Node.js app caolan's async and it's very nice. You can find it in github and a fine tutorial is available here. I believe that in your case you need a forEachSeries.
(Please try to limit each post to 1 question or if not possible at least to N related questions.)

Related

Why does my watcher gets called twice on the same change?

I have an AngularJS 1.4* application running locally (yet). This app is served by an Laravel 5.1 backend RESTFul API.
I have to make this app that represents a package trip. A package is composed by days, ranging from 0 to N days. Each day have a list of services, ranging from 0 to N services. And a hotel.
My web server, from which my laravel application consumes from, delivers me a pre-setted package, containing a list of days: each one with a list of services and a hotel data (unused so far). On the response I have a list of properties for the package (that don't matter for now) and an array of days, called days_info. That response is being put in the $scope.package, on my PackageController. The PackageController also declares an directive called packageBlock, that consists in a list of days, and some other data for the package.
<div ng-repeat="day in package.days_info" class='row'>
<div class='col-md-12'>
<package-days-block></package-days-block>
</div>
</div>
Inside <package-days-block> directive, I have another to iterate through the list of services inside every day.
<div class='container-fluid' ng-repeat='service in day.services' ng-controller="ServiceController">
<service-block></service-block>
</div>
That's where the problem begins: to my undestandment, I now have a $scope.service inside my ServiceController. So, I started to change it on my need inside the ServiceController through a $scope.service.
The $scope.service has an attribute called service_id. I put a listener/watcher on it, so at any time the $scope.service.service_id is changed, I ask for another service_table (holds the informations about the services, it's based on the service_id previously choosen or changed by the user), and put it in the $scope.service.table.
// ServiceController
$scope.reloadServicesTable = function(service_id, service_day, date, paxes){
MandatoryService.getServiceTable(service_id, service_day, date, paxes)
.then(
function(service_data) {
$scope.service.table = service_data;
},
...
);
The reloadServicesTable is called on the watcher for the service_id changes.
// ServiceController
$scope.$watch(
'service.service_id', // Places the watcher to watch the changes on the service's ID.
function(new_service, old_service) {
if( new_service === old_service )
return;
$scope.reloadServicesTable($scope.service.service_id, $scope.service.service_day, $scope.day.date, $scope.package.paxes);
}
);
The problem starts here: the request for the service's table is called twice when the service_id only changes once.
WHY, GOD, WHY?!
There's another part of my code where I, from the PackageController, run through the entire days_info array and reads the value of an attribute price inside the service.table: service.table.price. In there, I realise that there's two scope's: the one I handling and the other that I have no FREAKING IDEA where it came from!
If I put an console.log($scope); inside the method that runs through the days_info, I get two scopes for every request. This method is on the PackageController.
Any ideas why this is happening?
P.S.: It's my very first AngularJS application, so, take easy if I messed up on something basic...
EDIT:
As pointed out by an fellow on the comments, my question wasn't very reproducible. Sadly, I can't put here only the part I'm having doubts cause I don't have the slightest idea where the problem lies! (I know that this isn't much of help)
I took some screen shots from the Chrome Console:
First, the requestions fired on the change of the service_id
As you can see, every request is called twice everytime. This is not an one-time-thing. The /api/service/{id}... is the call for the service's table information. The /api/service/by_route/origin/... returns an list of services from one city to another (or the same). One does not interfere on the other.
The other image is the output from a console.log from the PackageController $scope, on the time that the service_id is being changed.
As you can see, there's two different scopes. And the b scope is son of the r scope. The r scope is also calling the watcher on the service_id?
The call for the sums price is been called twice from differente places, as you can see in the image below:
It may solve you issue. Even i had faced exactly the same as you are mentioning.
The reason for me was that, the controller was getting initialized again and there was a separate api call written in that, which was intended to load the page initially.
There can also be a scenario where you have assigned controller twice in the mark up.
<div ng-repeat="day in package.days_info" class='row'>
<div class='col-md-12'>
<package-days-block day="day"></package-days-block>
</div>
</div>
<div class='container-fluid' ng-repeat='service in day.services'>
<service-block service="service"></service-block>
</div>
Pass day and service down into directives. Use two way binding to pass your day and service changes back up to package.days_info.
Remove your ServiceController It does not make much sense to ng-repeat a controller. <service-block> and <package-days-block> are E directive that handle logic.
Write only one watcher in your PackageController that watch package.days_info When your day or service change, it can simply find out and do something about it.
Just Chill and fix it.

How to paint the response of an ajax in a new window by angular?

I am pretty new with angular js. My use case is We have a parent page say parentPage.html where we have a link. On click of this link in parentPage I want to send a server hit to a spring controller, which should return us a json response. I want to paste this response in the new window against the childpage.html. How can we achieve this by angular js?
parentPage.html:
Show New Customer
ajax response on click of above link:
{
customerName:'Adam',
address:'XYZ',
}
childPage.html(we have to iterate over the above key value pairs such that our result should be painted in the following way:-)
<table>
<tr>
<td>customerName:</td>
<td>Adam:</td>
</tr>
<tr>
<td>address:</td>
<td>XYZ:</td>
</tr>
</table>
On google I found enough stuff about the means by which we have to bring things within the scope. My only confusion in this usecase is, since we have to open a new window after sending the http get request(which is being sent from the parentPage.html), the response of which is to be painted in an absolutely new window(which is childPage.html), so isn't this scope going to get lost somewhere since we are not dealing with SPA thing here? Can we achieve this by angular in any possible way?
Since angular is meant to work off a one page application and retain the state of most javascript throughout the duration of the application being ran, you really have two option.
The first is to take that JSON response and store it in local storage.
window.localStorage.setItem('key', value);
By doing this, you will be able to pull the value back out at any point by use of the following
value = window.localStorage.getItem('key');
In most cases, you would want to stringify() the JSON before parsing it all out again.
This is one implementation which would definitely work out for you.
Another option would be to make use of ng-model, models are used to store and manipulate data in angularjs, By passing around these values back to your controllers you will be able to easily hold and interact with the state of these variables.

Angular reload data for ng-repeat without ugly refresh all items?

I do have a message system where all the inbox messages are displayed:
<div ng-repeat="msg in inbox.messages">
// here the message
</div>
Works fine. Now i want to use a polling system to get possible new messages, sent by other users. I wrote a pollingService with this piece of code:
$timeout(function() {
$rootScope.inbox = MessagesInbox.get();
self.run();
}, 10000);
Now each 10 seconds, the messages are pulled with ajax and are assigned to inbox. Now the ng-repeat updates... But it is ugly because is is rendered again and thus blinking the page.
Is there a way to update my messages another way, so that it will look neat?
You could do a comparison of what is currently in the inbox vs. what comes back from the service, and then add/delete/edit only those records that have changed.

How to use $resource in AngularJS properly for building a client app?

I've been following this tutorial http://draptik.github.io/blog/2013/07/28/restful-crud-with-angularjs/. I implemented a Grails backend with it instead of the Java one in the tutorial.
I've got the data coming back and forth, with one issue. If I create/update/delete a user, I don't see the changes reflected on my user list when I am redirected back. I have to refresh the page to see the updates.
Looking at the network traffic for an edit, it looks like it does a PUT and fires off the GET before the PUT is complete. Assuming this is because $resource returns a promise so things can be done asynchronously. So how do I handle this so that when $location redirects me, my list is up to date?
I'm guessing the options are to wait for the PUT to complete before redirecting/querying for the list, or to somehow manually manage the $scope.users to match the request?
Or maybe this tutorial is just a bad example? Maybe there is a better way to do it (still using $resource)?
Note: I've seen Restangular out there, and I've seen $http with success callbacks, but I would like to understand the situation above.
One way to overcome this issue would be to not redirect to the list page, till you get a callback, and then do a redirect. You can show some busy indicator till that time. The resource call looks like this.
resource.update(config,data,function() { //gets called on success},
function(error) { //gets called on failure});
In real life scenario waiting for the response of update makes sense as you want to handle the error and success scenarios on the same page.
I don't see your code anywhere so i'm just assuming (based on what you wrote and your current problem)
You are probably doing a full (or partial) get each time you changed a user and (re)binding the result to your scope. Doing this in the callback of the resource should actually start the digest cycle angular does to update modified objects. If you had been doing the fetching outside $resource - for example with custom/jquery ajax you would need to execute $scope.$apply()
What i really don't understand you would need to wait for the callback. You already know you added/modified a user. Instead of 'detaching' that user from your scope, modify it, post it to your rest server, then wait for callback, and reinserting it into the scope - why not modify it directly in the list/array you put on your scope?
var users = Users.get(function () {
$scope.users = users.record; // bind the resulting records to the scope
});
$scope.updateUser = function (user) {
resource.update(...); //pseudo
};
Then in your html, you will keep a reference to the currentUser and the div-list will update automaticly.
<div ng-repeat="user in users" ng-click="currentUser=user">{{user.Name}}</div>
<input ng-model="currentUser.Name">
<button ng-click="updateUser(currentUser);">Update</button>
If you don't want to see the update in the list while you type, but only once your callback fires or when you hit the button, would would instead use another ng-model for your input like this:
<input ng-model="tempUser.Name">
And you would then copy the value other in either the updateUser method or in the resource callback like this:
$scope.updateUser = function (user) {
user.Name = $scope.tempUser.Name; // should update automaticly
resource.update(...) // pseudo
}
Hope it helped!

Angularjs Search in large data set with pagination

currently I use filter:query for searching within the data, something like this
<input type="text" ng-model="query">
<tr ng-repeat="thought in thoughts | filter:query">
<td>thought.title</td>
</tr>
It works well, if I load the complete json data at once.
Now my question is can I achieve server side search along with pagination as I don't want to load the complete data set at once?
One approach : For the current result set search can be performed normally using filters, if no results are found make a call to server requesting the another piece of data. Is this approach good ?
Well, assuming you have a API/CGI on your server which executes the searches and returns a subset (e.g. by using SQLs limit start,number) it shall not be that complicated to achieve this. When you start a new query you would set thoughts to a empty array and then make the first API call, e.g. returning 10 results. And then you could have a button or whatever mechanism to make the next API call, returning result 11-20. In your $http callback function you would then simply always append the data returned by the server to your array, so that new data is added at the end. So think of something like this (this is no actual tested code, just written down for the sake of this answer):
$scope.getdata = function() {
$http.post('/api/whatever',
{ query: $scope.query, startat: $scope.thoughts.length })
.success(function(response,status,headers,config){
$scope.thoughts.push.apply( $scope.thoughts, reponse.data );
});
$scope.search = function() {
$scope.thoughts = [];
$scope.getdata();
}
Search for: <input ng:model="query">
<button ng:click="search()">Search</button>
<button ng:click="getdata()">Get more results</button>
There's not going to be any way to do a client-side search unless you load all the data into the client with your first ajax request.
Server side search is probably gonna be your best bet.

Resources