Cant read property from service in angular - angularjs

In this case console logged all properties
app.controller("sgCtrl", function ($scope, $service)
{
var asd=service.getPerson();
console.log(asd);
}
But when im try to get some property its returned me undefined
...console.log(asd.person.Id)
My service
function service($http, $q) {
var service = {
person:[]
};
service.getPerson = function (personId) {
return $http.get('/P/GetP',
{params:{personId:personId}}).success(function (res) {
service.person = res.Person;
});
};

Issue is
1. $http.().success(function() {}) is asynchronous function. So service.person will be available only when control will come inside success callback handler.
2. You have not created service in the correct way.
You can try with below code:
Service code
function service($http, $q) {
this.getPerson = function (personId, successHandler) {
$http.get('/P/GetP',
{params:{personId:personId}}).success(function (res) {
successHandler(res.Person);
});
};
app.service('MyService', service);
Controller Code
app.controller("sgCtrl", function ($scope, MyService) {
function successHandler(person) {
console.log(person.IsActive);
}
MyService.getPerson('somePersonId', successHandler);
}
I believe it will resolve your issues.
Cheers!

Related

Getting Undefined in controller

I'm trying to get the value from service and then printing that value in console log which is giving me undefined in controller.
The value from service is being returned properly. But I'm not able to access vm.rrsData outside getRRSDetails function. vm.rrsData is comming as undefined outside the function.
Please suggest.
my controller :
(function () {
'use strict';
var angular = window.angular;
function RRSCtrl(
$translate,
RRSSvc
) {
var vm = this;
// Private
function getRRSDetails() {
RRSSvc.getRRSDetails()
.then(function (data) {
vm.rrsData = data;
});
}
getRRSDetails();
console.log('vm.rrsData'+ JSON.stringify(vm.rrsData)); // returning undefined here
}
angular
.module('quote')
.controller('RRSCtrl', [
'$translate',
'RRSSvc',
RRSCtrl
]);
}());
my service :
(function () {
'use strict';
var angular = window.angular;
function RRSSvc(
$http,
$q,
UserSvc,
UtilitiesSvc
) {
function rrsError(messageKey) {
UtilitiesSvc.showMessage(messageKey, 'error', 'generate-blank-demo-error');
}
function getRRSDetails(poID) {
return $http.get('quote/accounts/' + UserSvc.get('accountId') + '/pos/' + poID + '/rrs?serialNumber=')
.then(function (response) {
return response.data;
})
.catch(function (e) {
rrsError('quote.messages.GET_RRS_ERROR');
$q.reject(e);
});
}
return {
getRRSDetails: getRRSDetails
};
}
angular.module('quote')
.service('RRSSvc', [
'$http',
'$q',
'UserSvc',
'UtilitiesSvc',
RRSSvc
]);
}());
That's completely normal since you're making an asynchronous request.
consider these 2 lines:
getRRSDetails();
console.log('vm.rrsData'+ JSON.stringify(vm.rrsData)); // returning undefined here
console.log will run before the function above resolves. So, at that time vm.rrsData is undefined.
To see the value you must include console.log inside the function:
function getRRSDetails() {
RRSSvc.getRRSDetails()
.then(function (data) {
vm.rrsData = data;
console.log('vm.rrsData'+ JSON.stringify(vm.rrsData)); // has value from the http call
});
}
UPDATE
Another way to write the above and maybe more clear:
RRSSvc.getRRSDetails().then(onRSSDetails);
function onRSSDetails(response) {
// here you do whatever you want with data.
console.log(response);
}
Try to call your service in controller like this:
this.rrsData = null; //declare variavle to store service data
RRSSvc.getRRSDetails()
.then(function (data) {
this.rrsData = data;
}.bind(this)); // bind is the key to store the context
console.log('rrsData'+ JSON.stringify(this.rrsData));

Angular: Mocking a Data Service

I'm doing unit testing for the first time and I'm trying to work out how to mock a data call from a service so I can test if the data is coming back in the correct form:
My Service
angular.module('app.core')
.factory('PeopleService', PeopleService)
function PeopleService($http, $q, $filter) {
var endpoint;
var service = {
customers: {
value: null
},
getAllCustomers: getAllCustomers,
};
return service;
function getCustomers(endpoint_) {
endpoint = endpoint_;
service.customers.value = [];
return handleFetch($http.get(endpoint));
}
function handleFetch(promise) {
return promise.then(function (resp) {
service.customers.value = service.customers.value.concat(resp.data.data);
});
}
function getAllCustomers() {
return $q.all([
getCustomers('/api/customers'),
]).then(function(responses) {
return responses[0];
});
}
}
My Controller
angular.module('app.people')
.controller('peopleCtrl', peopleCtrl);
function peopleCtrl($scope, PeopleService) {
$scope.customers = PeopleService.customers;
getCustomers();
function getCustomers() {
return PeopleService.getAllCustomers().then(function () {
return PeopleService.customers.value;
});
}
}
My Test
describe('People Service', function () {
var controller;
var customers = mockData.getMockCustomers(); // my fake customers array
beforeEach(function() {
bard.appModule('app');
bard.inject('$controller', '$q', '$rootScope', 'PeopleService');
var ps = {
getAllCustomers: function() {
return $q.when(customers);
}
};
controller = $controller('peopleCtrl', {
$scope: $rootScope,
PeopleService: ps
});
});
it('should return an array of 5 customers', function() {
$rootScope.$apply();
expect($rootScope.customers).to.have.length(5);
});
});
I've got a controller set up that when loaded talks to the People Service and gets my customers and saves the array of customers to PeopleService.customers.value. Inside my controller, I have a variable $scope.customers which is equal to PeopleService.customers.
I'm trying to mock this with my test, without hitting the API, I'm using some mock data to do this (an array of 5 customers), but not sure if I understand correctly.
Is the idea to have my mock people service return exactly what the actual people service returns? I'm kind of confused at this point. I basically want that test to check if the mock data length is equal to five.
Any help with this is appreciated. Thanks in advance!

Scope Variable calling http service stays undefined

This might be a beginner question, but why does the $scope.usercountry Variable stays undefinded, although the service is successful?
http://jsfiddle.net/9twyLna1/
var myApp = angular.module('myApp', []);
myApp.factory('myService', function ($http) {
return {
userCountry: function () {
$http.get("http://ipinfo.io/json").success(function (data) {
var userCountry = data.country;
alert(userCountry);
return userCountry;
});
}
};
});
function MyCtrl($scope, myService) {
$scope.usercountry = myService.userCountry();
}
$http works in asynch way, what it means is when you call a service userCountry, an asynch call to the end point will be made and code will come back to the calling function. So basically you are trying to show the data before it is actually fetched. This is the basic behaviour when you work with promises.
To overcome this you will need to return a promise from the service and from calling function you should wait until data comes back from http request.
you can read about this here.
updated fiddle : http://jsfiddle.net/9twyLna1/3/
var myApp = angular.module('myApp', []);
myApp.factory('myService', function ($http) {
return {
userCountry: function () {
return $http.get("http://ipinfo.io/json");
}
};
});
function MyCtrl($scope, myService) {
$scope.usercountry = myService.userCountry().then(function(data){
return data.data.country;
});
}

Creating a service around Restangular in AngularJS is not returning array

I am new to AngularJS and Restangular. But being a good citizen I thought I would try to create some services.
While this works and I get an array back populating a drop down list:
Restangular.all('/ta/tas').getList().then(function(tas) {
$scope.therapyAreas = tas;
});
But when I create a service, and then inject the service into the controller I get nothing back:
.controller('prGPTCtrl',['$scope', 'prTAService', 'Restangular', function($scope, prTAService, Restangular) {
$scope.prGpts = {};
$scope.therapyAreas = {};
Restangular.setBaseUrl('resources/pr');
$scope.therapyAreas = prTAService.prTAList();
Service:
prServices.factory('prTAService', ['Restangular', '$q', function prTAService(Restangular, $q) {
return {
prTAList : function(therapyAreas) {
var therapyAreas = {};
Restangular.setBaseUrl('resources/pr');
Restangular.all('/ta/tas').getList().then(function(tas) {
therapyAreas = tas;
return therapyAreas;
}
);
}
};
}]);
I see it being called in Chrome Debugger...I suspect it is related to promises (which I don't really "get").
Update:
This works as a service:
prServices.factory('prTAService', ['Restangular', '$q', function prTAService(Restangular, $q) {
return {
prTAList : function(therapyAreas) {
Restangular.setBaseUrl('resources/pr');
return Restangular.all('/ta/tas').getList();
}
};
}]);
And this works when calling it, not sure what I am gaining here!
prTAService.prTAList().then(function(tas) {
$scope.therapyAreas = tas;
});
The service needs to return the promise and the controller will handle the return because this is asynchronous. You are doing it right in the last part there:
prTAService.prTAList().then(function(tas) {
$scope.therapyAreas = tas;
});

The ui router resolve result data is not injected in the controller

In my SchoolyearController the parameter schoolyears is undefined.
How can I retrieve my schoolyears objects in the schoolyearService and inject the result into the SchoolyearController?
SERVICE
'use strict';
angular.module('schoolyear').service('schoolyearService', function ($http) {
return {
getSchoolyears: function () {
var path = 'scripts/model/schoolyears.json';
$http.get(path).then(function (response) {
return response.data.schoolyears; // The schoolyears here are the 6 expected JS objects in an array, so far so good but how do I get those objects into the SchoolyearController as parameter ?
});
}
};
});
UI-ROUTER
resolve: {
schoolyearService: ['schoolyearService',
function (schoolyearService) {
return schoolyearService.getSchoolyears();
}]
},
CONTROLLER
'use strict';
angular.module('schoolyear').controller('SchoolyearController', function ($scope, schoolyears) {
$scope.schoolyears = schoolyears; // I do not want to do a $http request here I just want to get passed the data here !!!
});
UPDATE
Still the schoolyears in the resolved property are undefined, why?
FACTORY
'use strict';
angular.module('schoolyearModule').factory('schoolyearFactory', function ($http) {
return {
getSchoolyears: function () {
var path = 'scripts/model/schoolyears.json';
$http.get(path).then(function (response) {
return response.data.schoolyears; // The schoolyears here are the 6 expected JS objects in an array
});
}
};
});
UI-ROUTER
resolve: {
schoolyears: function(schoolyearFactory) {
var schoolyears = schoolyearFactory.getSchoolyears();
return schoolyears;
}
},
CONTROLLER
'use strict';
angular.module('schoolyearModule').controller('ProjectsController', function ($scope, schoolyears) {
$scope.schoolyears = schoolyears; // I do not want to do a $http request here I just want to get passed the data here !!!
});
Your resolved value is named schoolyearService (and thus clashes with the service which has the same name):
resolve: {
schoolyearService: ...
But you're trying to inject it using the name schoolyears:
angular.module('schoolyear').controller('SchoolyearController',
function ($scope, schoolyears) {
Use the same name (schoolyears) everywhere:
resolve: {
schoolyears: ...
Also, you should use the factory() method to define your service, and not the servoce() method. The service() method takes a constructor function as argument, not a function returning an object being the actual service instance.
EDIT:
Moreover, you're not returning anything from the getSchoolyears() service method. So undefined is returned. What you need is:
getSchoolyears: function () {
var path = 'scripts/model/schoolyears.json';
return $http.get(path).then(function (response) {
return response.data.schoolyears;
});
}

Resources