retrieve data with angularJS and parse - angularjs

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')}}

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);
};

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?

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

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>

angularfire binding to primitive

I'm trying to bind to a primitive with angularfire. Here's how I"m doing it:
$firebase(fb.child('counts/node')).$on('value', function (obj) {
$scope.nodeCount = obj.snapshot.value
})
Is this correct? This API seems very different from the rest of firebase. I expected to get an ss as callback and do ss.val() but that doesn't seem to be the case. Can someone confirm if this is how it's supposed to be or if I'm doing it wrong. Thanks.
Generally, as outlined in the getting started guide and API, you should simply be accessing the data directly in the view:
// javascript
$scope.messages = $firebase(new Firebase(URL));
<!-- html -->
<li ng-repeat="message in messages">{{message}}</li>
If you want to iterate the data in a controller (bad) or service (better), you can read the keys in the order as the database by using $getIndex().
// javascript
var ref = $firebase(new Firebase(URL));
ref.$on('loaded', function() {
angular.forEach(ref.$getIndex(), function(key) {
console.log('the next message is', key, ref[key]);
});
});
If you are, in fact, trying to synchronize a single primitive value, angularFire is hardly necessary:
$scope.primitive = null;
var ref = new Firebase(URL);
ref.on('value', function(snap) { $scope.primitive = snap.val(); });
$scope.saveValue = function(newValue) {
ref.set(newValue);
};
But certainly possible:
// javascript
$scope.primitive = $firebase(new Firebase(URL));
<!-- html -->
<input ng-model="primitive.$value" />
All of this is covered in the above links, which should be treated as required reading before getting started with Angular + Firebase.
changes in 0.8
angularFire 0.8 will be out soon. It will change this structure a little bit, utilizing a $asArray(), $asObject(), and also providing a .then() method, so a bit more like this:
// javascript
var ref = $firebase(new Firebase(URL));
$scope.messages = ref.$asArray();
$scope.ref.then(function() {
angular.forEach($scope.messages, function(message) {
console.log('the next message is', message.$id);
});
});
<!-- html -->
<li ng-repeat="message in messages">{{message}}</li>

How to use $resource in Angular to work with a RESTful api

I'm trying to add some basic CRUD functionality to MEAN stack. I've created a RESTful service that works and I'm confused about how to wire it all up. I can get it to work, but I want to make sure I'm doing things the best way and not creating an unnecessary hack.
My api route for a single Person is like this:
// Find one person
app.get('/api/person/:id', function(req, res) {
Person.find ( {_id: req.params.id },
function(err, data){
res.json(data);
}
)});
// Find group of people
app.get('/api/person', function(req, res) {
// use mongoose to get all people in the database
Person.find(function(err, data) {
res.json(data);
});
This seems to work in that if I go to a URI with an ID, as in localhost://3000/api/person/23423434, I see JSON data like this:
[
{
"_id": "532d8a97e443e72ef3cb3e60",
"firstname": "Horace",
"lastname": "Smith",
"age": 33
}
]
This tells me the basic mechanics of my RESTful api are working. Now I'd like to display that data with angular in a template like so:
<h3>{{ person.firstname + ' ' + person.lastname }} </h3>
To do that, I just need to create a $scope.person object with get() or query(). Here's the relevant part of my app:
angular.module('crudApp', ['ngRoute', 'ngResource'])
.config(['$routeProvider', function($routeProvider){
$routeProvider
.when('/api/person/:id',
{
templateUrl: 'partials/person.html',
controller: 'PersonCtrl'
});
}])
.factory('Person', function($resource){
return $resource('api/person/:id', { id: '#_id'});
})
.controller('PersonCtrl', function($scope, $routeParams, Person){
$scope.person = Person.get( { id: $routeParams.id } ); // Having trouble here!
});
The trouble I'm having is that get() fails with an error (Error: [$resource:badcfg]). On the other hand, if I use Person.query(), I get back an array, which means I need to change my template to the following:
<h3>{{ person[0].firstname + ' ' + person[0].lastname }} </h3>
This works, but seems strange and isn't like what I've seen in angular tutorials. The only other solution I've found is to set $scope.person in a callback:
Person.query({ id: $routeParams.id }, function(person){
$scope.person = person[0];
});
This works with my original unmodified template. Is it the best or right way to work with RESTful apis like this? Is there a better way?
Answer: the answer is in comment below. My problem is that api is using Person.find() but should be using Person.findOne( { _id: req.params.id }); Using findOne() returns a single object.
Your api should look like this:
route -> '/api/person/:id'
return single person
route -> '/api/person'
return array of persons
then if you want to get by id, you shall use get method, or if you want to get all persons, you should use query method. Your mistake is that you shall return single object when getting by id

Resources