How to keep Angular UI responsive during an http get request? - angularjs

I have a get request in my controller:
$http.get('/api/ideas').success(function(ideas) {
vm.ideas = ideas;
});
As soon as my controller is called, this api is called, and my UI becomes unresponsive until i get the result from the callback / all ideas are listed (with mg-repeat obviously). When i have e.g. 1000 ideas in my database, my UI is unresponsive for 3-5 seconds. But i thought that call was a callback ?!
This is how my backend looks like:
router.get('/api/ideas', controller.find);
exports.find = function(req, res) {
Idea.find(function (err, ideas) {
if(err) { return handleError(res, err); }
return res.json(200, ideas);
});
};
What is the problem here?
EDIT - SOLVED:
When i put a delay in backend like this:
exports.index = function(req, res) {
Idea.find(function (err, ideas) {
if(err) { return handleError(res, err); }
setTimeout(function() {
return res.json(200, ideas);
}, 3000);
});
};
although i just have 2 ideas, the UI is responsive during that 3 seconds. I can still click other parts till i get a response. So i think #Iggy is right. The problem is not the http get, but ng-repeat.

The problem is not the callback here (it's async), the problem is ng-repeat slowing your UI by adding your ideas one by one in the DOM.
To solve this you can use pagination, or look at the different way to improve ng-repeat performance.
A basic way to do so is to use the limitTo filter :
<div ng-init="totalDisplayed=20" ng-repeat="item in items | limitTo:totalDisplayed">
{{item}}
</div>
<button class="btn" ng-click="totalDisplayed = totalDisplayed+20">Load more</button>

Related

angulajs data on the page is not loading after route redirection

when I am at the home page and click on the link in the navigation bar
<li class="nav-item" ng-show="currentUser">
<a class="nav-link" ng-show="currentUser"
ng-href="#/pictures"">Pictures</a>
</li>
It goes to the page, I can see the data is downloaded but it is not shown in the UI when update $scope.urlListUI.
urlListInRoomUnits=loadPicture(filePathInRoomUnitPicture);
$scope.urlListUI=urlListInRoomUnits;
$scope.$apply();
console.log('update ui: '+urlListInRoomUnits);
however, if I refresh the page, it will work.
the UI code
<div ng-repeat = "urlRecord in urlListUI">
<p>{{urlRecord[1]}}</p>
<img ngf-src="urlRecord[0]" class="img-thumbnail">
</div>
the function: loadPicture(filePathInRoomUnitPicture)
function loadPicture(pictureTypeFolder){
console.log('loadpicture is running, input parameter:'+pictureTypeFolder);
var urlList=[];
$scope.whereThePictureIs=pictureTypeFolder;
//list image from firebase storage
var storageRefDownloadByPictureType = storageRef.child('airconPicture').child(pictureTypeFolder);
storageRefDownloadByPictureType.listAll()
.then(function(result) {
console.dir(result);
result.items.forEach(function(imageRef) {
// And finally display them
imageRef.getDownloadURL()
.then(function(url){
// TODO: Display the image on the UI
urlList.push([url,imageRef.name]);
})
.catch(function(error) {
// Handle any errors
});
});// end of for each download
})// end of list all promise
.catch(function(error) {
// Handle any errors
});
return urlList;
};// end of load Pciture by type
thanks for helping or direct me to the right source.
So what I see, first, you try to resolve storageRefDownloadByPictureType.listAll()
After resolving (let's say 1 sec), you run in a loop on results and try to resolve a list of items:
result.items.forEach(function(imageRef) {
imageRef.getDownloadURL().then(function(url){
})
You resolve all at once, let's say, another 1 sec.
Your method does not return promise but empty urlList because you populate it in the next 2 seconds.
So instead urlListInRoomUnits=loadPicture(filePathInRoomUnitPicture);
It should be something like (you can write loadPicture in some service, lets say MyService):
MyService.loadPicture(filePathInRoomUnitPicture).then(function (urls) {
//here you get all your results
$scope.urlListUI = //...
});
and now loadPicture in MyService:
this.loadPicture = function(filePathInRoomUnitPicture){
//...
return storageRefDownloadByPictureType.listAll().then(function(result) {
// create list of promises:
var promises = [];
result.items.forEach(function(imageRef) {
promises.push(imageRef.getDownloadURL());
})
// chain promises
return $q.all(promises);
};

Angular-chart not updating chart real-time when using timer [duplicate]

Based on changing the value of a variable I wish to display an error message in my html. I call an api from my angular code, and if it returns an error, I have set up a setInterval function that should update bookingData.tracking_id to false and then show an error message in the html. This should be very easy but combining this with setInterval is proving slightly difficult.
Here is the angular/javascript
this.confirmTrackingTest = function () {
TestService.finalPackageCheck({tracking_id: controller.bookingData.tracking_id}).$promise.then(function (data) {
return data;
}).catch(function (err) {
var i = 0;
var interval = setInterval(function () {
i += 1;
if (i === 3) {
if (err.statusText === "Not Found") {
controller.bookingData.showErrorMessage = true;
}
clearInterval(interval)
}
}, 2000);
console.log(controller.bookingData.showErrorMessage)
});
}
this.bookingData = {
showErrorMessage: false,
tracking_id: 1
};
Here is the html:
{{Packs.bookingData.showErrorMessage}}
<div class="alert alert-danger" role="alert" ng-if="Test.bookingData.showErrorMessage">
<p>Please show this message</p>
</div>
The {{Packs.bookingData.showErrorMessage}} shows false so that is recongised in the html.
Please let me know if any further information is required.
This is exactly the reason why the Angular gods invented $interval in order to remove the need to manually use $apply.
So either you call $scope.$apply inside the callback or you use $interval (don't forget to include it in the parameter list for depedency injection)

Angular JS ng-repeat doesn´t showing data correctly

I have a strange problem when using ng-repeat.
Only as additional information, I am using ui-router as well.
I did a test with a simple markup that query some data in my local node server and shows with ng-repeat.
To make the test, I click a button to add a new row to server and next, I query the server again to get the new rows updated.
The problem is that the server return correctly all data with the new row added included, but ng-repeat is no showing the rows just added.
Here is more details of the problem.
Firstly, when the page is loaded I have
RowId
1
2
After I click the "Add and Refresh Row" button, I´d expect to have on the screen:
RowId
1
2
5
But I still have only:
RowId
1
2
In console,I checked the return data from my server after I add a row and the data returned is:
{id:1,name:'John Doe'},
{id:2,name:'Mary Doe'}
{id:5,name:'teste'}
where item id=5 is the row just added, buit it doesn´t appears with ng-repeat.
What am I doing wrong?
//markup
<div ng-controller="configClinicaClinicaCtrl">
<a class="btn btn-sm btn-success" ng-click="saveClinica()">Add and Refresh Row</a>
<div>RowId</div>
<div ng-repeat="row in dados track by $index">
{{row.id}}
</div>
</div>
//local server with server.js script at node.js
var clinicas=[
{id:1,name:'John Doe'},
{id:2,name:'Mary Doe'}
];
//get clinicas
app.get('/clinicas', function(req, res) {
res.json(clinicas);
});
//insert clinica
app.post('/clinicas', function(req, res) {
clinicas.push(req.body);
res.json(true);
});
//controller
angular.module("clinang").controller('configClinicaClinicaCtrl',['$scope','$http', '$state', function($scope,$http, $state) {
$scope.dados={};
$scope.clinica={};
var refreshData=function(){
$http.get('/clinicas').then(function(response){
$scope.dados=response.data;
}, function(error){
console.log(error)
});
}
refreshData();
$scope.saveClinica=function(){
$scope.clinica.id=5;
$scope.clinica.nome='teste';
var clinica=$scope.clinica;
$http.post('/clinicas',{clinica}).then(function(response){
refreshData();
}, function(error){
console.log(error)
})
}
}]);
Whenever you do some form of operation outside of AngularJS, such as doing an API call you need to let AngularJS know to update itself. Try this,
var refreshData=function(){
$http.get('/clinicas').then(function(response){
$scope.dados=response.data;
$scope.$apply();
}, function(error){
console.log(error)
});
}

How to call Google Cloud Endpoints with AngularJs when the page Loads, to get user information(PICTURE, NAME..)

I am trying to make a post request using Google Cloud Endpoints and AngularJS when the page loads so I can get the user information and fill the profile picture, profile description and so on...
I am able to run requests when pressing a button or something like that but can't call the google endpoints automatically when the page loads and that is whats I am trying to achieve.
Below is the HTML part where the {{userPicture}} should've been loaded in the angular script:
(HTML)
<div class="form-group">
<label class="col-sm-3 control-label">Profile image</label>
<div class="col-sm-9" ng-controller='initController'>
<img src="{{userPicture}}" class="user-image-profile" alt="User Image">
</div>
</div>
(ANGULAR)
controllers.initController = function($scope, $http){
$scope.userForm = {
"userEmail" : $.cookie('auth')
};
gapi.client.igardenendpoints.getProfile($scope.userForm).execute(function(resp) {
$scope.$apply(function () {
if (resp.error) {
$scope.backmessage.messagetext = "GetProfile Error!"
console.log("error");
} else {
if (resp.userEmail == "TEMPLATE"){
$scope.backmessage.messagetext = "Error please try again!"
}else{
$scope.userPicture = 'https://filiperebollo1986.appspot.com/serve?blob-key=' + resp.profilePicKey;
}
}
});
});
}
error
I also tried to use the following:
$scope.initData = function () {
gapi.client.igardenendpoints.getProfile($scope.userForm)...........
}
and run the function at the end of the controller, like:
$scope.initData();
But both does not work, any help on that?
I will not be able to help you in 100% as I'm not using Google Cloud, but will try to do my best.
First of all, to get the data it's usually better to use services rather than do it in the controller.
But anyway, your problem seems to be different. In your HTML did you include your script and client API?
I was able to fix my problem and bellow is the solution:
The problem was that at the moment of my call, the script may not have been loaded once I was using the "ng-app" directive directly on the body TAG.
Now I am injecting the angular module dinamicaly just after my API loading:
function googleOnLoadCallback(){
var apisToLoad = 1; // must match number of calls to gapi.client.load()
var gCallback = function() {
if (--apisToLoad == 0) {
//Manual bootstraping of the application
var $injector = angular.bootstrap(document, ['authModule']);
console.log('Angular bootstrap complete ' + gapi);
};
};
gapi.client.load('igardenendpoints', 'v12', gCallback, '//' + window.location.host + '/_ah/api');
}
</script>
<script src="https://apis.google.com/js/client.js?onload=googleOnLoadCallback"></script>
And now It is working!!!!
The only problem now is that when the page loads it appears the {{example}} in the page, is it possible to avoid the {{}} to appear?

retrieve data with angularJS and parse

I'm trying to create an app using ionic framework which is angularJS and parse.com. And I would like to get data from parse.com into my app so I use the code.
var Category = Parse.Object.extend("category");
var query = new Parse.Query(Category);
query.find({
success: function(results) {
$scope.category = results;
},
error: function(error) {
alert("Error: " + error.code + " " + error.message);
}
});
and in HTML page I put
<a ng-repeat="cat in category" nav-clear menu-close class="item" href="#/app/board/{{cat.id}}">
{{cat.name_en}}
</a>
to repeat my data.
the results data is
[{"name_en":"property","name_th":"บ้าน/อพาร์ทเม้นท์","objectId":"tomiG6VzCd","createdAt":"2014-08-18T08:32:13.956Z","updatedAt":"2014-08-18T08:32:19.617Z"},{"name_en":"jobs","name_th":"หางาน/จ้างงาน","objectId":"9Aop8vzn6l","createdAt":"2014-08-18T08:32:32.792Z","updatedAt":"2014-08-18T08:32:36.485Z"},{"name_en":"motors","name_th":"ซื้อ/ขายรถยนต์","objectId":"vLwjhWVJOm","createdAt":"2014-08-18T08:32:55.475Z","updatedAt":"2014-08-18T08:32:58.610Z"},{"name_en":"other","name_th":"อื่นๆ","objectId":"6xVpnrSMrW","createdAt":"2014-08-18T08:33:08.178Z","updatedAt":"2014-08-18T08:33:13.453Z"}]
but when I ten the app, it seem like information doesn't show on the list, so my app displayed like this picture.
like they and see how many rows from parse.com but they can't get name_en to show on the list.
any suggestion to fix this problem.
Thank you.
The success and error callbacks are executed in the context of the Parse library, so Angular is not made aware of the changes on $scope.category. Try to use $scope.$apply to make Angular aware of the change:
success: function(results) {
$scope.$apply(function () {
$scope.category = results;
});
},
In your Html, instead of
{{cat.name_en}}
put
{{cat.get('name_en')}}

Resources