Can't reach field inside an object in my angular controller - angularjs

I'm using a factory to get a television show from a database. I wanted to send just the episodes field from this object to a angular service but I keep getting undefined using dot notation and bracket notation. Can someone explain how to get this field.
Controller
angular.module('showApp.controllers', []).controller('ShowViewController', function($scope, $stateParams, Show, $http) {
$scope.show = Show.get({ id: $stateParams.id }); //Get a single show.Issues a GET to /api/shows/:id
console.log($scope.show)
console.log($scope.show.episodes)
})
Console Output
m
$promise:d
$resolved:true
__v:0
_id:"581a5b82ff9e9f10f22afff7"
airs_on:Array[1]
episodes:Array[11]
genre:Array[3]
network:"Netflix"
poster:"https://images-na.ssl-images-amazon.com/images/M/MV5BMTk5NTk1Mzg3Ml5BMl5BanBnXkFtZTcwNDAyNzY3OA##._V1._CR25,3,1010,1343_SY1000_CR0,0,752,1000_AL_.jpg"
program_time:60
rated:"TV-MA"
streams_on:Array[3]
title:"Black Mirror"
yearBegin:2011
__proto__:Object
undefined

you can wait for results by:
$scope.show.$promise.then(function(show) {
console.log(show.episodes);
})
you should call the service in the then function.

I think this is a timing issue. There should be a callback from the http get request, at which time $scope.show is valid - you should do your console logging in the callback

Related

Utilising $scope.apply()

I have the following which works fine, drawing info from a RESTful api feed
app.controller('servicesController', ['$scope', '$location', '$http', '$interval',
function($scope, $location, $http, $interval) {
var getData = function() {
// Initialize $scope using the value of the model attribute, e.g.,
$scope.url = "https://(remote link to JSON api)";
$http.get($scope.url).success(function(data) {
$scope.listOfServices = data.runningServices; // get data from json
});
};
getData();
$interval(getData(), 10000);
}
]);
However my view is not updating every 10 seconds as expected. I have read that I need to use $scope.apply() somewhere in this above code.
I tried placing the following (in the appropriate place above)
$http.get($scope.url).success(function(data) {
$scope.listOfServices = data.runningServices; // get data from json
$scope.apply(); //I also tried $scope.runningServices.apply()
});
$scope.apply is not your problem, the scope will be digested automatically at the end of the $http request and $interval. Certain actions automatically "inform" Angular that the scope may have changed and trigger a digest; only if you're writing "non-Angular" code may you have to explicitly trigger a scope digest, since otherwise Angular wouldn't notice any changes.
No, your issue is that you're calling getData(), and then have its return value (undefined) execute every ten seconds. Which is obviously nonsense. You just want to pass the function itself to $interval:
$interval(getData, 10000);
// look ma, ^^^^^, no parentheses

Fetch an external json file through Angular JS

I am trying to implement a faceted search based on AngularJS https://github.com/kmaida/angular-faceted-search
As the example is based on a dataset incorporated in the JS, I am trying to load the JSON File remotely. (total noob in angularJS by the way).
In the example, the Controller is defiend as:
myApp.controller('MainCtrl', function($scope, Helpers) {
And there are 2 helpers defined
myApp.factory('Helpers', function() {...
I am trying to inject the $http in a third helper, my code:
,
//below line 30 in https://github.com/kmaida/angular-faceted-search/blob/master/app.js
fetchData: function (){
var resultjson=[]
$http.get('/api/data.json').success(function(data) {
resultjson=data
console.log(data);
});
console.log(resultjson);
return resultjson;
}
The newly defined variable resultjson has a value in the success function, but no value beyond that point.
Any one can help me fetch the data correctly? Appreciate the support.
If you want to receive data from $http, you will have to use promises. Right now, you are returning resultjson before the value has been received from the api end point.
You should return promise, and once the promise is resolved, the value will be in the promise.
Due to the fact, that $http returns promise, you can return it directly, without wrapping it in another promise.
fetchData: function (){
return $http.get('/api/data.json');
}
and you can access the data in your your controller and assign to the scope:
Helpers.fetchData().then(function(data){
$scope.items = data.data;
})

Cannot access Firebase object attributes. Value displayed as undefined ANGULARFIRE

I want to do a custom login for a demo of my doing, but I encountered a problem.
I use the username to access a reference url inside Firebase, I get a returned object. If I want to access a single attribute, I get the undefined value, but if I add in my html {{returnedObj.name}} the value is displayed.
Why is that?
angular.module('Demo').controller('loginCtrl', ['$scope', '$firebase', '$location', function($scope, $firebase, $location){
$scope.user = {};
$scope.check = function(){
console.log('https://fabritzio-demo.firebaseio.com/users/' + $scope.user.name);
$scope.returnedObj = $firebase(new Firebase('https://fabritzio-demo.firebaseio.com/usuarios/' + $scope.user.name)).$asObject();
alert($scope.returnedObj.name); // returns undefined value
};
}]);
Firebase values are loaded asynchronously. The value will not yet have been loaded into $scope.returnedObj when the alert fires.
There are a couple of ways to handle values loading asynchronously from Firebase, for example using $loaded to get a promise:
$scope.returnedObj.$loaded().then(function () {
alert($scope.returnedObj.name);
});
The value is displayed in the template because Angular watches all $scope variables for changes. When the value is loaded (milliseconds later), it is immediately displayed.

AngularJS: make data received with $http inside factory to be accessible inside controller

I have a factory called "Server" which contains my methods for interaction with the server (get/put/post/delete..). I managed to login and get all data successfully when I had all my code in my controller. Now that I want to separate this code and restructure it a little bit I ran into problems. I can still login and I also get data - but data is just printed; I'm not sure how to access the data in controller? I saw some ".then" instead of ".success" used here and there across the web, but I don't know how exactly.
This is my factory: (included in services.js)
app.factory('Server', ['$http', function($http) {
return {
// this works as it should, login works correctly
login: function(email,pass) {
return $http.get('mywebapiurl/server.php?email='+email+'&password='+pass').success(function(data) {
console.log("\nLOGIN RESPONSE: "+JSON.stringify(data));
if(data.Status !== "OK")
// login fail
console.log("Login FAIL...");
else
// success
console.log("Login OK...");
});
},
// intentional blank data parameter below (server configured this way for testing purposes)
getAllData: function() {
return $http.get('mywebapiurl/server.php?data=').success(function(data) {
console.log("\nDATA FROM SERVER: \n"+data); // here correct data in JSON string format are printed
});
},
};
}]);
This is my controller:
app.controller("MainController", ['$scope', 'Server', function($scope, Server){
Server.login(); // this logins correctly
$scope.data = Server.getAllData(); // here I want to get data returned by the server, now I get http object with all the methods etc etc.
…. continues …
How do I get data that was retrieved with $http within a factory to be accessible in controller? I only have one controller.
Thanks for any help, I'm sure there must be an easy way of doing this. Or am I perhaps taking a wrong way working this out?
EDIT: I also need to be able to call factory functions from views with ng-click for instance. Now I can do this like this:
// this is a method in controller
$scope.updateContacts = function(){
$http.get('mywebapiURL/server.php?mycontacts=').success(function(data) {
$scope.contacts = data;
});
};
and make a call in a view with ng-click="updateContacts()". See how $scope.contacts gets new data in the above function. How am I supposed to do this with .then method?(assigning returned data to variable)
My question asked straight-forwardly:
Lets say I need parts of controller code separated from it (so it doesn't get all messy), like some functions that are available throughout all $scope. What is the best way to accomplish this in AngularJS? Maybe it's not services as I thought …
The trick is to use a promise in your service to proxy the results.
The $http service returns a promise that you can resolve using then with a list or success and error to handle those conditions respectively.
This block of code shows handling the result of the call:
var deferred = $q.defer();
$http.get(productsEndpoint).success(function(result) {
deferred.resolve(result);
}).error(function(result) { deferred.reject(result); });
return deferred.promise;
The code uses the Angular $q service to create a promise. When the $http call is resolved then the promise is used to return information to your controller. The controller handles it like this:
app.controller("myController", ["$scope", "myService", function($scope, myService) {
$scope.data = { status: "Not Loaded." };
myService.getData().then(function(data) { $scope.data = data; });
}]);
(Another function can be passed to then if you want to explicitly handle the rejection).
That closes the loop: a service that uses a promise to return the data, and a controller that calls the service and chains the promise for the result. I have a full fiddle online here: http://jsfiddle.net/HhFwL/
You can change the end point, right now it just points to a generic OData end point to fetch some products data.
More on $http: http://docs.angularjs.org/api/ng.%24http
More on $q: http://docs.angularjs.org/api/ng.%24q
$http.get retuns a HttpPromise Object
Server.getAllData().then(function(results){
$scope.data = results;
})

How do you access loaded data from .$on('loaded') in AngularFire 0.5.0

I am having trouble accessing the data loaded from firebase using the .$on method in AngularFire 0.5.0
In the callback when I log out the contents of the scope the data is there but when I try to use deeper data I get undefined. Perhaps I am misunderstanding how you are meant to access data in this method?
This is my controller:
.controller('AssetDetailCtrl',
['$scope', '$firebase', 'FBURL',
function($scope, $firebase, FBURL) {
var refAsset = new Firebase(FBURL + '/assets/' + $scope.assetId);
$scope.asset = $firebase(refAsset);
// when data is loaded check validity of the route
$scope.asset.$on('loaded', function() {
console.log($scope.asset); // complete with the asset data
console.log($scope.asset.name); // undefined even though it appears in the above console log
});
}])
So perhaps there is a better way to do this.Why is it I cannot access the data from the scope the even though it logs to the console?
This is the result of the first console.log
Object { $bind: function, $add: function, $save: function, $set: function, $remove: function…}
$add: function (b,c){var d;return d="object"==typeof b?a._fRef.ref().push(a._parseObject(b),c):a._fRef.ref().push(b,c)}
$bind: function (b,c){return a._bind(b,c)}
$child: function (b){var c=new AngularFire(a._q,a._parse,a._timeout,a._fRef.ref().child(b));return c.construct()}
$getIndex: function (){return angular.copy(a._index)}
$on: function (b,c){switch(b){case"change":a._onChange.push(c);break;case"loaded":a._onLoaded.push(c);break;default:throw new Error("Invalid event type "+b+" specified")}}
$remove: function (b){b?a._fRef.ref().child(b).remove():a._fRef.ref().remove()}
$save: function (b){b?a._fRef.ref().child(b).set(a._parseObject(a._object[b])):a._fRef.ref().set(a._parseObject(a._object))}
$set: function (b){a._fRef.ref().set(b)}
asset_author: Object
collections: Array[2]
creator: "John Doe"
desc: "a description of the asset"
file: "http://lorempixel.com/400/200/sports/3/"
filesize: "28kb"
filetype: "jpg"
name: "Cycling"
release: "12/12/2013"
tags: "tag1, tag3"
type: "Photography"
__proto__: Object
Second console.log returns undefined
Based on Kato's answer here I have been able to solve this.I was unaware the loaded event passed the raw data of the loaded asset, it is undocumented in the AngularFire docs.
It doesn't explain the odd behaviour I was having with console.log but it does solve the problem.
.controller('AssetDetailCtrl',
['$scope', '$firebase', 'FBURL',
function($scope, $firebase, FBURL) {
var refAsset = new Firebase(FBURL + '/assets/' + $scope.assetId);
$scope.asset = $firebase(refAsset);
// when data is loaded check validity of the route
$scope.asset.$on('loaded', function(value) {
console.log(value); // data loaded from Firebase
console.log(value.name); // subset of the returned value
});
}])
Just for my own sake and others out there that may be having the same issue as i did, stumbling upon this question googling for the answer. My problem was that sometimes i was getting undefined as the value from the callback of $on('loaded').
The way i solved it in the end was to use that event as a way of knowing when i could call the resource.$getIndex(), and the use the indexes returned from that to loop through the content and possibly store that in a new array to access the raw data.

Resources