Why I'm getting the var undefined - javascript

I'm trying to get a Rest array and then display it on my HTML.
the problem that I'm facing is that In My factory I'm able to get the array and display it's content, but not in my controller where I'm always getting the Undefined var. here is my Factory
.factory('coursesService', function($resource) {
var service = {};
service.getAllCouses = function (){
var Courses = $resource("/myproject/rest/training/trainings");
var data = Courses.query().$promise.then(function(data)
{
service.data= data;
console.log("ligne 1: ", service.data[0].name);
console.log("ligne 1: ", service.data[0].creator);
console.log("ligne 2: ", data[1].name);
console.log("ligne 2: ", data[1].creator);
return service.data;
});
}
return service;
})
and my controller
.controller("CoursesController",
function CoursesController($scope, coursesService) {
var courses = {};
courses = coursesService.getAllCouses();
console.log("courses: ", courses);
})
as results I'm getting this:
courses: undefined
ligne 1: Angular
ligne 1: Object {id: "1", username: "User1", email: "user1#gmail.com", password: "password", userProfile: Object}
ligne 2: JavaScript
ligne 2: Object {id: "1", username: "User1", email: "user1#gmail.com", password: "password", userProfile: Object}
Why I'm getting courses: undefined? and Shouldn't be displayed after the list that I'm displaying in the factory?

Your getAllCouses function never returns anything, and so calling it always results in undefined. The callback to the query promise then handler returns something, but not getAllCouses.
You'll need to have getAllCouses return the promise, and then use the result from within a then handler on that promise. You can't just use its return value directly, not if Courses.query() is async (and if it isn't, why is it returning a promise?).
That would look something like this:
.factory('coursesService', function($resource) {
var service = {};
service.getAllCouses = function (){
var Courses = $resource("/myproject/rest/training/trainings");
var data = Courses.query().$promise.then(function(data) {
service.data= data;
console.log("ligne 1: ", service.data[0].name);
console.log("ligne 1: ", service.data[0].creator);
console.log("ligne 2: ", data[1].name);
console.log("ligne 2: ", data[1].creator);
return service.data;
});
return data; // <=== Return the promise (`data` is a bit of a suspect name)
};
return service;
})
Then:
.controller("CoursesController", function CoursesController($scope, coursesService) {
coursesService.getAllCouses().then(function(courses) { // <=== Use the promise
console.log("courses: ", courses); // <===
}); // <===
})
...but I'm not an Angular guy.

getAllCouses() does not return a value, it just sets two local variables, Courses and data.
The Courses.query promise only resolves once the web request is complete, so those logs are delayed.

I fixed the issue by updating my service and controller like this:
.factory('coursesService', function($resource) {
return $resource("/myproject/rest/training/trainings", {
query : {
method : "GET",
isArray : true
}
});
});
I just added the
isArray : true
and i updated the controller
.controller(
"CoursesController",
function UserController($scope, coursesService) {
coursesService.query(function(data) {
console.info("data: ", data)
console.log("1st course: ", data[0].name)
$scope.Courses = data;
});

I fix it simply in this way:
.factory('coursesService', function($resource) {
return $resource("/myproject/rest/training/trainings")
})
and the controller:
.controller("coursesController", function($scope, coursesService) {
coursesService.query(function(data) {
$scope.Courses = data;
});
})

Related

Best practice to get a json response object in angularjs

I have an API which return a json array object, right now, I get the json in my Controller like this and it works just fine :
angular.module('lyricsApp', [])
.controller('LyricsController', ['$scope', 'ApiCall', function ($scope, ApiCall) {
$scope.lyrics = {
id: "",
songName: "",
singerName: "",
writtenBy: "",
lyricText: "",
isEnable: "",
created_at: "",
updated_at: ""
};
$scope.searchLyric = function () {
var result = ApiCall.GetApiCall().success(function (lyrics) {
$scope.lyrics.id = lyrics.data.id
$scope.lyrics.singerName = lyrics.data.singerName;
$scope.lyrics.songName = lyrics.data.songName;
$scope.lyrics.writtenBy = lyrics.data.writtenBy;
$scope.lyrics.lyricText = lyrics.data.lyricText;
$scope.lyrics.isEnable = lyrics.data.isEnable;
$scope.lyrics.created_at = lyrics.data.created_at;
$scope.lyrics.updated_at = lyrics.data.updated_at;
});
}
}])
But I think this is not a good practice, I already try this :
var result = ApiCall.GetApiCall().success(function (lyrics) {
$scope.lyrics=lyrics.data;
});
in this case I get undefined value :
console.log($scope.lyrics.id); // show Undefined
So, if you guys can suggest a better way I will be appreciate it.
You are doing the right thing, except for console.log. If your log statement is executed before the assignment is done, you will get the undefined value.
Also I don't see why you would do a var result =
You can simply do
ApiCall.GetApiCall('v1', 'lyrics', '1').success(function (data) {
$scope.lyrics = data.data;
console.log($scope.lyrics.id);
}).error(fucntion(data){
console.log(data);
});

How to synchronize the function commands in angular js

I am creating an ionic application and in particular scenario
when an employee is selected from a list(generated from a JSON data array), his detail is to be shown from here
var employees = [{"id": 325, "firstName": "James", "lastName":
"King", "managerId": 0, "managerName": "", "reports": 4, "title":
"President and CEO", "department": "Corporate", "cellPhone":
"617-000-0001", "officePhone": "781-000-0001", "email":
"jking#gmail.com", "city": "Boston, MA", "pic": "James_King.jpg",
"twitterId": "#fakejking", "blog": "http://coenraets.org"}.....
All i need is to find the index of ID to show the complete object.
findById: function(employeeId) {
var deferred = $q.defer();
var searchValue = {'id': employeeId };
index = -1;
_.each(employees, function(data, idx) {
if (_.isEqual(data, searchValue)) {
index = idx;
return;
}
});
var employee = employees[index];
deferred.resolve(employee);
return deferred.promise;
},
for that i am using this function which is not taking debugger inside the _.each function
kindly tell me where m i wrong.
It's not going to work because expression _.isEqual(employees[xxx], {id: 325}) will never return a match.
Instead use _.find method
findById: function(employeeId) {
var employee = _.find(employees, {id: employeeId});
return $q.when(employee);
}
I think you can simplify your function a little, because you are using lodash:
findById: funtion(employeeId) {
return _.findWhere(employees, {id : employeeId});
}
Futhermore I do not see any reason to use promises here, but to go with that notion, you could try this:
findById: funtion(employeeId) {
var deferred = $q.defer();
$timeout(function() {
var employee = _.findWhere(employees, {id : employeeId});
if (found !== undefined) {
deferred.resolve(employee);
} else {
deferred.reject();
}, 0);
return deferred.promise;
}
You need to return the promise deferred.promise before you resolve() or reject(), so you can wait for that in your callee.
Hope that helps!
I don't know if your really need the index. To work on a solution, which returns the employee at that moment, when you find the data, would be better and shorter. Than you should also jump out of the loop.
If your debugger is not jumping inside _.each maybe your employees array is empty.
You could try something like this:
findById: function(employeeId) {
var deferred = $q.defer();
// deferred should be inside the scope of _.each
// because it is defined here
var searchValue = {'id': employeeId };
//index = -1;
// check your data here
// for example console.log(employees.length)
// or make a breakpoint here and check employees
_.each(employees, function(data, idx) {
// make a console.log(idx) here to check your data
if (_.isEqual(data, searchValue)) {
deferred.resolve(data);
return deferred.promise;;
}
});
},

Why is $httpProvider.interceptors returning an `undefined` value

I've created a basic AngularJS app that consumes Yelp's API and am having trouble using $httpProvider.interceptors to parse my response.
Here is my app:
var app = angular.module("restaurantList", []);
My yelpAPI service (not pictured) authenticates my API request and generates a HTTP request. I then output the data received to the Web Console like so:
app.controller("mainCtrl", ["$scope", "yelpAPI", function ($scope, yelpAPI) {
$scope.restaurants = [];
yelpAPI.get(function (data) {
$scope.restaurant = data;
console.log($scope.restaurant);
});
}]);
Here is data from my request:
Object {region: Object, total: 37, businesses: Array[20]}
I want the array located in the businesses property. So, I figured it would be a good idea to use $httpProvider.interceptors to parse the objects found, in the Object.businesses array.
Here is what $httpProvider.interceptors looked like, when I made my initial request:
app.config(function ($httpProvider) {
$httpProvider.interceptors.push(function () {
return {
response: function (response) {
return response;
}
}
});
});
Here is what $httpProvider.interceptors looks like now:
app.config(function($httpProvider) {
$httpProvider.interceptors.push(function() {
return {
response: function(response) {
var old_response = response.businesses,
new_response = [];
for (var i = 0; i < old_response.length; i++) {
var obj = old_response[i],
new_obj = {
restaurant_name: obj.name,
phone_number: obj.display_phone,
yelp_rating: obj.rating,
reservation_url: obj.reservation_url
};
new_response.push(new_obj);
}
return new_response;
}
}
});
});
Now, I'm receiving an error that says TypeError: Cannot read property 'businesses' of undefined. Is there something I'm overlooking?
EDIT #1
I used console.log(response) inside the interceptor to print my response and found that response.businesses should actually be response.data.businesses. Which resolves my error but now my $http call returns undefined. Any idea what my new problem could be?
EDIT #2
app.factory("yelpAPI", function($http, nounce) {
return {
get: function(callback) {
var method = "GET",
url = "http://api.yelp.com/v2/search";
var params = {
callback: "angular.callbacks._0",
oauth_consumer_key: "my_oauth_consumer_key",
oauth_token: "my_oauth_token",
oauth_signature_method: "HMAC-SHA1",
oauth_timestamp: new Date().getTime(),
oauth_nonce: nounce.generate(),
term: "American",
sort: 2,
limit: 20,
radius_filter: 4000,
deals_filter: true,
actionlinks: true
};
var consumerSecret = "my_consumer_secret",
tokenSecret = "my_token_secret",
signature = oauthSignature.generate(method, url, params, consumerSecret, tokenSecret, {
encodeSignature: false
});
params["oauth_signature"] = signature;
$http.jsonp(url, {
params: params
}).success(callback);
}
}
});
In return angular wait object with {data : }:
app.config(function($httpProvider) {
$httpProvider.interceptors.push(function() {
return {
response: function(res) {
var old_response = res.businesses,
new_response = [];
for (var i = 0; i < old_response.length; i++) {
var obj = old_response[i],
new_obj = {
restaurant_name: obj.name,
phone_number: obj.display_phone,
yelp_rating: obj.rating,
reservation_url: obj.reservation_url
};
new_response.push(new_obj);
}
return {data : new_response};
}
}
});
});
Return as {data : new_response}
Emir helped me resolve this issue but essentially, whenever you use $httpProvider.interceptors you have to update response.data and return the entire response object (i.e. not just a new array, as I did) because $http selects the data property for you.

Return result to parent function

I have been pulling my hair out here. I am using ion-autocomplete and want to pull data with a factory.
My Factory ...
myApp.factory('items', function($http){
return {
list: function(query,callback){
$http.get('http://192.168.100.100/myApp/products/' + query).success(callback)
}
};
});
To get the data I use ..
items.list(function(items) {
$scope.items = items;
});
The demo for autocomplete request data like ..
$scope.getTestItems = function (query) {
return {
items: [
{id: "1", name: query + "1", view: "view: " + query + "1"},
{id: "2", name: query + "2", view: "view: " + query + "2"},
{id: "3", name: query + "3", view: "view: " + query + "3"}]
};
};
So I figure this is a workable solution ..
$scope.getTestItems = items.list(query,function(items)
{
console.log(items);
return items;
}
)
but clearly is not. I have tried ..
$scope.getTestItems = function(query)
{
items.list(query,function(items)
{
console.log(items);
return items;
}
)
}
Which does give me a console of the result but this is not returned to getTestItems
According to the docs (assuming I've got the right lib here), you can return a promise
myApp.factory('items', function($http){
return {
list: function(query) {
return $http.get(... + query).then(function(res) {
return res.data; // unwrap the response data
// see the "Returns" section at https://docs.angularjs.org/api/ng/service/$http#usage
});
}
};
});
and the controller
$scope.getTestItems = function(query) {
return items.list(query);
};
How about this
Factory
list: function(query,callback){
return $http.get('http://192.168.100.100/myApp/products/' + query)
}
In this way you are returning the promise from the factory.
Controller
$scope.getTestItems = function(query){
items.list(query).then(function(items){
console.log(items);
});
}
The callback will execute as soon as the promise resolves.
you could try this,
myApp.factory('items', function($http){
return {
list: function(query){
return $http.get('http://192.168.100.100/myApp/products/'+query);
}
};
});
then in your controller
var promise = items.list(query);
promise.then(function(response){
//here we go
$scope.items = angular.fromJson(JSON.parse(response.data));
});

Angular resource response interceptor

I want to create a Custom Action on Resource, which will process the results received from the server.
angular.module('problem', ['ngRoute', 'ngResource'])
.factory('Abc', function ($resource) {
return $resource('api/abc/:abcId', {abcId: '#id'}, {
customQuery: {
method: "GET",
isArray: true,
interceptor: {
response: function (response) {
// some operations that manipulate data based od response
response.data = [5, 6]; // for simplifity
console.log("manipulation finished"); // log is saved
return response;
}
}
}
}
);
})
;
But when I use the Custom Action, I get the unmodified results instead of processed.
Here is the code showing the expected behavior (and in comments relevant errors):
describe('Abc', function () {
beforeEach(module('problem'));
var $httpBackend;
beforeEach(function () {
angular.mock.inject(function ($injector) {
$httpBackend = $injector.get('$httpBackend');
})
});
it('should return converted array when customQuery called', inject(function (Abc) {
$httpBackend
.expectGET('api/abc')
.respond([
{id: 'uid1', name: 'name1'},
{id: 'uid2', name: 'name2'},
{id: 'uid3', name: 'name3'},
{id: 'uid4', name: 'name4'}
]);
var result = Abc.customQuery();
$httpBackend.flush();
expect(result.length).toBe(2); // fails with "Expected 4 to be 2."
expect(result[0]).toBe(5); // fails with "Expected { id : 'uid1', name : 'name1' } to be 5."
expect(result[1]).toBe(6); // fails with "Expected { id : 'uid2', name : 'name2' } to be 6."
}));
});
Maybe what you need is to add a new transformResponse transformation, you can easily do that like this (remember to inject $http):
transformResponse: $http.defaults.transformResponse.concat([
function (data, headersGetter) {
return data.objects
}
Difference is, result will be substituted by response.resource, while the return value of the interceptor is the value that is resolving result.$promise
thank you for the "interceptor" idea!
in my opinion
response.data = [5, 6]; // for simplifity
return response;
should return a response-object, with a property-array "data", so
result.length;
should fail.
For manipulating the results of a resource response better use response.resource instead of response.data - there are the real REST objects (with CRUD methods)

Categories

Resources