Scope Variable calling http service stays undefined - angularjs

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

Related

Resource file is undefined on scope

I have a resource file that sometimes is read, and sometimes is undefined and crashes all the application. I do not know why it only works sometimes and it is causing me trouble to figure a solution out. On my controllers I am passing the service that I created to read the file which is appResourcesService:
app.controller('CommonController', ['$scope', '$location', 'appResourcesService',
function ($scope, $location, appResourcesService)
And the service to read resoruces is the following:
'use strict';
app.factory('appResourcesService', ['$resource', function ($resource) {
var appResourcesServiceFactory = {};
appResourcesServiceFactory.getResources = function ($scope, language, locale) {
var languageFilePath = 'resources/AppResources.json';
$resource(languageFilePath).get().$promise.then(function (data) {
$scope.appResources = data;
}, function (reason) {
var defaultLanguageFilePath = 'resources/AppResources.json';
$resource(defaultLanguageFilePath).get(function (data) {
$scope.appResources = data;
});
});
};
return appResourcesServiceFactory;
}]);
Like I said, sometimes it works without any kind of problem, but sometimes when in the controller I reach the piec eof code $scope.appResources, appResources is undefined. I think it is maybe because it reaches there before the file is read, but I am not being able to find a solution to avoid it.
Your factory should return a promise.
It's the job of your controller to handle data. (I use $http as it's cleaner)
app.factory('appResourcesService', ['$http', function($http) {
var appResourcesServiceFactory = {};
appResourcesServiceFactory.getResources = function () {
var languageFilePath = 'resources/AppResources.json';
return $http.get(languageFilePath).then(function(response) {
return response.data;
});
)};
return appResourcesServiceFactory;
}]);
You resolve the promise inside the controller with .then to get the data and set your scope.
appResourcesServiceFactory.getResources().then(function(data) {
$scope.appResources = data;
})

Cant read property from service in angular

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!

$scope not able to get data from factory using $http.get in Angularjs

<script>
var app = angular.module('myApp', ['ngMaterial']);
app.factory('factoryProvider', function ($http, $q) {
var facObj = {};
facObj.getLastWorkplace = $http.get('plugins/wcf-service/ServiceProvider.svc/getLastWorkPlacesJSON')
.then(function (response) {
return response.data;
});
return facObj;
});
app.controller('dashboardController', function ($scope, factoryProvider) {
factoryProvider.getLastWorkplace.then(function (successResponse) {
$scope.wp = successResponse;
console.log('inside');
console.log($scope.wp); // Return an object that I want
});
console.log('outside');
console.log($scope.wp); // $scope.wp is empty
});
The outside console log runs first, inside console log is the second. The problem is that $scope.wp can just get data in getLastWorkplace callback functions and it can not bind data to ng-model(using wp.property). How to solve it?
Thanks for your reading
You are assigning $scope.wp twice and the final assignment is the return value of your getLastWorkplace call (which you aren't returning anything.)
Change it to this...
factoryProvider.getLastWorkplace.then(function (successResponse) {
$scope.wp = successResponse;
});
or...
$scope.wp = factoryProvider.getLastWorkplace;
but not both.

Angular Service Undefined

In the code snippet below, I'm getting "ReferenceError: 'ShoppingListService' is undefined". I can't see what the error might be, been banging my head against it and searched for a while now, anyone have clues?
var ShoppingListApp = angular.module('ShoppingListApp', [])
ShoppingListApp.factory('ShoppingListService', ['$http', function ($http) {
var ShoppingListService = {};
ShoppingListService.getListItems = function () {
return $http.get('/ShoppingList/GetListItems');
};
return ShoppingListService;
}]);
ShoppingListApp.controller('ShoppingListController', function ($scope) {
getItems();
function getItems() {
ShoppingListService.getListItems() //Error occurs here
.success(function (shoppingItems) {
$scope.items = shoppingItems;
console.log($scope.items);
})
.[removed for brevity].
The error occurs in the area indicated above. Angular.js version 1.4.9.
In your controller definition ShoppingListController you just have one injectable called $scope you need to add a second one called ShoppingListService.
ShoppingListApp
.controller('ShoppingListController', ShoppingListController);
ShoppingListController.$inject = ['$scope', 'ShoppingListService'];
function ShoppingListController($scope, ShoppingListService) {
getItems();
function getItems() {
ShoppingListService
.getListItems() //Error occurs here
.success(onSuccess);
}
function onSuccess(shoppingItems) {
$scope.items = shoppingItems;
console.log($scope.items);
}
//other code
}

pass data between controllers in AngularJS dynamically [duplicate]

This question already has answers here:
Share data between AngularJS controllers
(11 answers)
Closed 2 years ago.
i have tow controller in angularjs. if one controller change data other controller display updated data. in fact first controller has a event that it occur second controller display it. for this propose i wrote a service. this service has tow function. here is my service code.
app.service('sharedData', function ($http) {
var data=[]
return {
setData: function () {
$http.get('/getData').success(function(response){
data = response;
})
},
getData: function(){
return data;
}
}
});
in first controller
app.controller("FirstController", function ($scope, $http,sharedData)
{
$scope.handleGesture = function ($event)
{
sharedData.setData();
};
});
in second controller:
app.controller("SecondController", function ($scope,sharedData) {
var data=[];
data = sharedData.getData();
}
);
in first controller setData work with out any problem but in second controller not work correctly. how to share data dynamically between tow controllers?
You are on the right track with trying to share data between controllers but you are missing some key points. The problem is that SecondController gets loaded when the app runs so it calls sharedData.getData() even though the call to setData in the firstController does not happen yet. Therefore, you will always get an empty array when you call sharedData.getData().To solve this, you must use promises which tells you when the service has data available to you. Modify your service like below:
app.service('sharedData', function ($http, $q) {
var data=[];
var deferred = $q.defer();
return {
setData: function () {
$http.get('/getData').success(function(response){
data = response;
deferred.resolve(response);
})
},
init: function(){
return deferred.promise;
},
data: data
}
})
And the secondController like this:
app.controller("SecondController", function ($scope,sharedData) {
var data=[];
sharedData.init().then(function() {
data = sharedData.data;
});
});
For more info on promises, https://docs.angularjs.org/api/ng/service/$q
You had multiple syntax problems, like service name is SharedData and you using it as SharedDataRange, the service is getting returned before the get function.
What I have done is corrected all the syntax errors and compiled into a plunkr for you to have a look. Just look at the console and I am getting the data array which was set earlier in the setter.
Javascript:
var app = angular.module('plunker', []);
app.controller("FirstController", function ($scope,sharedDateRange)
{
sharedDateRange.setData();
});
app.controller("SecondController", function ($scope,sharedDateRange) {
var data=[];
data = sharedDateRange.getData();
console.log(data);
});
app.service('sharedDateRange', function ($http) {
var data=[];
return {
setData: function () {
data = ['1','2','3'];
}
,
getData: function(){
return data;
}
}
});
Working Example
If you want to keep sharedDataRange as the variable name and service name as sharedData have a look at this example
javascript:
var app = angular.module('plunker', []);
app.controller("FirstController", ['$scope','sharedData', function ($scope,sharedDateRange)
{
sharedDateRange.setData();
}]);
app.controller("SecondController", ['$scope','sharedData', function ($scope,sharedDateRange) {
var data=[];
data = sharedDateRange.getData();
console.log(data);
}]);
app.service('sharedData', function ($http) {
var data=[];
return {
setData: function () {
data = ['1','2','3'];
}
,
getData: function(){
return data;
}
}
});
You can bind the data object on the service to your second controller.
app.service('sharedData', function ($http) {
var ret = {
data: [],
setData: function () {
$http.get('/getData').success(function(response){
data = response;
});
}
};
return ret;
});
app.controller("FirstController", function ($scope, sharedData) {
$scope.handleGesture = function () {
sharedData.setData();
};
});
app.controller("SecondController", function ($scope, sharedData) {
$scope.data = sharedData.data;
});
What you need is a singleton. The service sharedData needs to be a single instance preferably a static object having a static data member. That way you can share the data between different controllers. Here is the modified version
var app = angular.module('app', []);
app.factory('sharedData', function ($http) {
var sharedData = function()
{
this.data = [];
}
sharedData.setData = function()
{
//$http.get('/getData').success(function(response){
this.data = "dummy";
//})
}
sharedData.getData = function()
{
return this.data;
}
return sharedData;
})
.controller("FirstController", function ($scope, $http,sharedData)
{
sharedData.setData();
})
.controller("SecondController", function ($scope,sharedData) {
$scope.data=sharedData.getData();
});
I have removed the event for testing and removed the $http get for now. You can check out this link for a working demo:
http://jsfiddle.net/p8zzuju9/

Resources