AngularJS : Injecting Service in app.run - javascript

I want to initialize a globle variable "$rootScope.SegmentSelectedGlobal" at the starting of application only.
This globle variable get data from a service.
If i execute service through controller, its working fine.
But when i execute it from App.run, no value is being assinged an d no error is being reported.
Here is the code:
App.run :
app.run(['$rootScope','DashboardService', function($rootScope,DashboardService) {
$rootScope.SegmentSelectedGlobal = DashboardService.getSegments();
}]);
Service :
app.service("DashboardService",function($q,$http,errorMessages){
var allSegements = [];
return {
// For selected Only
getSegments : getSegments
}
function getSegments(){
var deferred = $q.defer();
$http({
url: "/getAllSegments",
method: "GET"
}).success(function (data, status, headers, config) {
deferred.resolve(data);
allSegements = data;
}).error(function (data, status, headers, config) {
//logger.logError('Error while retrieving Versions details');
allSegements = null;
});
return allSegements;
}
});
Thanx for your help.

It returns undefined because at return allSegements allSegements is undefined.
Your using a promise, yet your forgot to return it properly
app.service("DashboardService",function($q,$http,errorMessages){
var allSegements = [];
return {
// For selected Only
getSegments : getSegments
}
function getSegments(){
var deferred = $q.defer();
$http({
url: "/getAllSegments",
method: "GET"
}).success(function (data, status, headers, config) {
deferred.resolve(data);
allSegements = data;
}).error(function (data, status, headers, config) {
//logger.logError('Error while retrieving Versions details');
deferred.reject();//--------- REJECT IF ERROR
});
return deferred.promise;//------- RETURN THE PROMISE
}
});
app.run(['$rootScope','DashboardService',function($rootScope,DashboardService) {
// use then to get the data from your promise ince it's ready
DashboardService.getSegments().then(function(data){
$rootScope.SegmentSelectedGlobal = data;
});
}]);
Note if you want to wait for the promised to be resolved before loading your page, use the resolve attribute (available in both ngRoute/ui-router) :
resolve:{
segments:['DashboardService', function(DashboardService){
return DashboardService.getSegments();//we return the promise, the resolve parameter will take the result, in case of error page won't be loaded.
}];
}

Related

AngularJS - Best approach for taking data from factory and if not there use http service

In my angularJS application, I have set data received from one controller's ajax and put in factory method to reuse in other controllers. The problem is when user reload page, this factory method is useless.
app.factory('factory', function () {
return {
set: set,
get: get
}
});
app.controller ('testController', function ($scope, factory) {
if (factory.get('name')) {
$scope.name= factory.get('name');
} else {
$http.get(url).then(function(res) {
$scope.name= res.name;
factory.set('name', res.name);
});
}
});
What is the best way to retrieve this check in factory method which will get value from factory, if not there take from http service and in controller common code needs handle these two cases that done factory method?
Here when data taken from http service it returns promise otherwise plain value.
This code will fetch data from server if the 'cachedResult' variable is not set, otherwise return a promise from the stored variable.
app.factory('factoryName', ['$http','$q', function($http,$q) {
var cahedResult = null;
var myMethod = function(args) {
var deferred = $q.defer();
if (cahedResult){
deferred.resolve({ data : cahedResult });
return deferred.promise;
}
$http.get(....).then(function(response){
cahedResult = response.data;
deferred.resolve({ data : cahedResult });
},function(error){
deferred.reject('error');
});
}
};
return {
myMethod : myMethod
}
])
But you could also store the data in local storage or in a cookie when the first controller fetch the info so that it's available even if user refresh the browser.
First create a factory :
app.factory('factoryName', ['$http','$q', function($http,$q) {
return {
getData : function(arg1,arg2) {
return $http.get('/api-url'+arg1+'/'+arg2)
.then(function(response) {
if (typeof response.data === 'object') {
return response.data;
} else {
return $q.reject(response.data);
}
}, function(response) {
return $q.reject(response.data);
});
}
}
}])
Provide every api details in this factory, so you can use this factory in multiple controllers.
In Controller inject the factory (factoryName) as a dependency.
app.controller ('testController',['$scope', 'factoryName', function($scope, factoryName) {
factoryName.getData(arg1,arg2,...)
.then(function(data) {
console.log(data);
}, function(error){
console.log(error);
});
}]);
For detailed description :- http://sauceio.com/index.php/2014/07/angularjs-data-models-http-vs-resource-vs-restangular/
Directly return a promise from your factory
app.factory('factoryName', function () {
var connectionurl ='...'; //Sample: http://localhost:59526/Services.svc
return {
connectionurl : connectionurl ,
methodName: function (parameters) {
$http({
method: 'GET',
url: connectionurl + 'servicemethod_name'
})}
}
}
});
In this case your controller will look like
app.controller ('testController', function ($scope, factoryName) {
factoryName.methodName(parameters).then(function(){
$scope.variable=response.data;
/*binding your result to scope object*/
}, function() {
/*what happens when error occurs**/
});
});
Other way is directly bind to a scope object through success callback function
app.factory('factoryName', function () {
var connectionurl ='...'; //Sample: http://localhost:59526/Services.svc
return {
connectionurl : connectionurl ,
methodName: function (parameters,successcallback) {
$http({
method: 'GET',
url: connectionurl + 'servicemethod_name'
}).success(function (data, status, headers, config) {
successcallback(data);
})
.error(function (data, status, headers, config) {
$log.warn(data, status, headers, config);
});
}
}
});
In this case your controller will look like
app.controller ('testController', function ($scope, factoryName) {
factoryName.methodName(parameters,function(response){
/* your success actions*/
$scope.variable=response;
});
});
In the second case your error is handled in the factory itself. How ever you can also use errorcallback function.

how to call $scope.function1 from $scope.function2

I have a controller with the two functions.function "fileHistory" will be loaded first.
and i need to same call the same function from another function success callback.
i tried this way- but i am getting error
here is my Controller code
function cBookController($scope,$http) {
$scope.fileHistory = function() {
$http({
url: '/123/rest/getUploadDetails',
method: "GET"
})
.success(function (data, status) {
console.log(data);
$scope.fileHistory = data;
})
.error(function (data, status) {
alert("Error in get history details process");
});
}
$scope.fileHistory();
$scope.checkStatus = function(uploadedFileId) {
$http({
method: 'GET',
url: '/123/rest/checkStatus',
})
.success(function(data, status, headers, config) {
//here i need to get the new datafrom fileHistory service.
$scope.fileHistory();
})
}
}
By checking in your code I see that inside the $http success callback of fileHistory function, you override your function with response data from $http
Your fileHistory is a function at first. But after your promise is executed you are assigning this to a data variable and overriding it.
Change following line to something else -
//$scope.fileHistory = data; // change this line
$scope.fileHistoryData = data;

Angular $scope not available outside my function

Somewhat new to Angular and javascript. I have the following controller written use a factory service to access a local JSON file. Most of this code is derived (or completely taken) from this post by Dan Wahlin. I am unable to access the $scope.books variable outside of the function and cannot figure out why. The console.log inside the function gives me the object I am looking for, but the one outside returns undefined. What am I doing wrong here? Thanks.
app.controller('FormController', ['$scope', 'tocFactory', function ($scope, tocFactory) {
$scope.books;
getBooks();
function getBooks() {
tocFactory.getBooks().
success(function(data, status, headers, config) {
$scope.books = data;
console.log($scope.books);
}).
error(function(data, status, headers, config) {
// log error
})
}
console.log($scope.books);
}]);
Because you are making an ajax and then executing the next line of code. Which doesn't mean you have guarantee that your ajax response is ready on execution of next line of code.
You could always gets its response value inside the success function of $http which gets called when ajax call executed successfully.
Read here How asynchronous call works?
actually this isn't an issue of scope, but timing. The getBooks function is executed asynchronously, so when your console log happens it most likely will not have been bound to anything. You could test this easily with interval to see how this is happening:
app.controller('FormController', ['$scope', 'tocFactory', function($scope, tocFactory) {
$scope.books;
getBooks();
function getBooks() {
tocFactory.getBooks()
.success(function(data, status, headers, config) {
$scope.books = data;
console.log($scope.books);
})
.error(function(data, status, headers, config) {
// log error
})
}
setInterval(function(){
console.log($scope.books);
}, 1000);
}]);
You can use $q service to handle asynchronous code with promises :
app.controller('FormController', ['$scope', '$q', 'tocFactory', function ($scope, $q, tocFactory)
{
var getBooks = function()
{
var deferred = $q.defer();
tocFactory.getBooks().
success( function(data, status, headers, config)
{
$scope.books = data;
deferred.resolve();
} ).
error( function(data, status, headers, config)
{
deferred.reject();
} );
return deferred.promise;
};
getBooks().then( function(res)
{
console.log($scope.books); // success : your data
}, function(res)
{
console.log($scope.books); // error : undefined
} );
console.log($scope.books); // undefined
} ] );
I haven't tested this code but it should work and show you promises principle.
More about $q service : https://docs.angularjs.org/api/ng/service/$q

AngularJS service gets the data, but doesn`t return it to the controller?

scope.membersWarnings in controller is always empty, but in service it gets the data from the server. Somehow my data from the server is lost between callback of get function in service and controller.
Controller:
AndreaApp.controller('MemberDetailController', ['$scope', '$rootScope','$http','$location','$routeParams','MemberService','MemberGroupsService','ArrivalsService','WarningsService','NotificationsService',function (scope,rootScope, http,location,routeParams,MemberService,MemberGroupsService,ArrivalsService,WarningsService,NotificationsService) {
scope.member = MemberService.get(routeParams.id);
scope.membersGroup = MemberService.membersGroup(routeParams.id);
scope.membersWarnings = WarningsService.get(routeParams.id);
scope.editMember = function(id){
location.path('/editMember/'+id);
}
scope.membersDocument = function(id){
location.path('/membersDocument/'+id);
}
scope.templates =
[ { name: 'packages.html', url: 'views/members/packages.html'},
{ name: 'notifications.html', url: 'views/members/notifications.html'},
{ name: 'warnings.html', url: 'views/members/warnings.html'},
{ name: 'arrivals.html', url: 'views/members/arrivals.html'} ];
scope.template = scope.templates[0];
scope.loadTemplate = function(templateId){
if(templateId == 3){
scope.arrivals = ArrivalsService.get(routeParams.id).arrivalsId;
console.log(scope.arrivals);
}
scope.template = scope.templates[templateId];
}}]);
WarningsService:
AndreaApp.service('WarningsService', function ($http,$q) {
var warnings = [];
this.save = function (warnings, memberId) {
$http.post('/api/warnings/new/member/'+memberId,
{
name: warnings.name,
description: warnings.description,
readed: false,
clanId: memberId
}).
success(function(data, status, headers, config) {
}).
error(function(data, status, headers, config) {
alert("Error occurred while adding a warning. HTTP Respone: " + status);
});
}
this.get = function (id) {
var deferred = $q.defer();
$http.get('/api/warnings/member/'+id).
success(function(data, status, headers, config) {
warnings.length = 0;
console.log(data);
for(var i = 0; i < data.length; i++){
warnings.push(data[i]);
}
deferred.resolve(data);
//data exists here, it is not empty
}).
error(function(data, status, headers, config) {
alert("HTTP status:" + status)
});
return deferred;
}});
You could just return the $http, like this:
this.get = function (id) {
return $http.get('/api/warnings/member/'+id);
}
Then you could use it on the Controller.
WarningsService.get(routeParams.id).then(function(result){
$scope.membersWarnings = result.data; // or just result
});
You cant just assign like you're doing, because you're returning a promise this way. The result isnt ready yet at that moment
scope.member = MemberService.get(routeParams.id);
Should be
MemberService.get(routeParams.id).then(function(data) {
scope.member = data;
});
This is because your get method is returning a promise, so once it is resolved, u can obtain the data.
Also, your get method needs to be changed to
return deferred.promise;

ngResource query returns strange objects

I am new to AngularJS and wanted to try out the $resource functionality.
I have this code:
.factory('GetTasksService', function($resource, BASE_URL) {
return $resource(BASE_URL + 'api/tasks');
})
.controller('TasksCtrl', function ($scope, $http, BASE_URL, GetTasksService) {
$scope.tasks = GetTasksService.query();
$scope.getTasks = function () {
$http({ url: BASE_URL + 'api/tasks', method: 'GET' })
.success(function (data, status, headers, config) {
$scope.tasks = data;
})
.error(function (data, status, headers, config) {
alert("call did not work");
});
}
});
The getTasks function works as expected - returning an array of:["taska", "taskb"] as it should.
The GetTasksService.query() however returns an array of [{"0":"t","1":"a","2":"s","3":"k","4":"a"}, {"0":"t","1":"a","2":"s","3":"k","4":"b"}]
Can anyone tell me what I am doing wrong?
There is an option when specifying an action for an ngResource called isArray;
The default action query sets this as true by default, so you need to set set the action like:
query : {
method : 'GET',
isArray : false
}

Categories