Resource file is undefined on scope - angularjs

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

Related

$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.

Injecting a Angular service into controller results in $injector:unpr error (using AngularBooter)

I am using the AngularBooter for Angular in my app.
Here is my code:
emp.boot();
emp.services.SocialService = ['$http', '$q', function ($http, $q) {
var deferred = $q.defer();
$http.get('/api/feed').then(function (data) {
deferred.resolve(data);
});
this.getStatuses = function ()
{
return deferred.promise;
}
}];
emp.controllers.StatusesController = ['$scope','SocialService', '$interval', function($scope, SocialService, $interval) {
var statuses = SocialService.getStatuses();
statuses.then(function(data) {
$scope.statuses = data;
console.log($scope.statuses);
});
}];
From what I understand the error: Error: [$injector:unpr] is a sign that the service isn't being registered or implemented correctly, I have tried a few things but keep running into the same problem. Any ideas.
Two problems:
1) You are booting before you register your stuff (at least in the code you provided). Do emp.boot() right at the bottom after everything has been defined.
2) Your service is not returning anything. For instance, if you add return {}; at the very bottom of your service function, it should magically not throw the error anymore, but you probably want to return something more interesting than that.
You can see this in action by uncommenting the line that returns the object and see Angular start working again.
http://codepen.io/alex-wilmer/pen/QbwNGz?editors=101
I imagine you probably want something like this:
emp.services.SocialService = ['$http', '$q', function ($http, $q) {
var deferred = $q.defer();
$http.get('/api/feed').then(function (data) {
deferred.resolve(data);
});
return {
getStatuses = function () { // don't mix brace placement!
return deferred.promise;
}
};
}];

Content of an XML File with $http not available outside the .succes() context

I have a service xmlService which uses the $http service to read an XML-File. Everything is working fine, but when I use my xmlService in one of my controllers it returns an empty object, although the $http.get() is successfull. I have no idea whats the problem.
Update:
I understood that the $http-call is asyncronous thus I have to use the $q service. I'm not sure if I understood the $q API correctly because my updated code doesn't work either. I also read an tutorial like this one: http://www.bennadel.com/blog/2612-using-the-http-service-in-angularjs-to-make-ajax-requests.htm - But I can't find the mistake, because I probably didn't understand something.
My Service
angular.module('tvc.Services.Xml', []);
angular.module('tvc.Services.Xml')
.service('xmlService', ['$http', '$log', '$q', 'x2js', function($http, $log, $q, x2js) {
return function(file) {
var deferred = $q.defer(),
parsedFile = {};
$http
.get(file).success(function(data) {
parsedFile.fileContent = data;
parsedFile.json = x2js.xml_str2json(data);
deferred.resolve(parsedFile);
})
.error(function(data) {
$log.warn('Unable to load: ' + file);
});
return deferred.promise;
};
}]);
console.log(parsedFile); returns:
{
fileContent: '<xml>...</xml>',
json: {..},
__prototype__: {...}
}
My Controller
.controller('KeyaccountsController', ['$scope', 'xmlService', function($scope, xmlService) {
$scope.keyaccounts = {};
xmlService('assets/xml/ops_merge_data2.xml').then(function(data) {
$scope.keyaccounts = data;
});
console.log($scope.keyaccounts);
}]);
console.log($scope.keyaccounts); returns:
{}
Since the $http.get() is asynchronous, the return is happening before the success happens, and thus parsedFile is undefined.
You either need to return the promise (i.e., return $http.get(file) and then do all of the logic that you're doing in your controller, or use the angular $q service, like this:
angular.module('tvc.Services.Xml', []);
angular.module('tvc.Services.Xml')
.service('xmlService', ['$http', '$log', 'x2js', '$q', function($http, $log, x2js, $q) {
return function(file) {
var deferred = $q.defer();
var parsedFile = {};
$http
.get(file).success(function(data) {
parsedFile.fileContent = data;
parsedFile.json = x2js.xml_str2json(data);
deferred.resolve(parsedFile)
})
.error(function(data) {
$log.warn('Unable to load: ' + file);
});
return deferred.promise;
};
}]);
And then your controller would be like:
.controller('KeyaccountsController', ['$scope', 'xmlService', function($scope, xmlService) {
xmlService('assets/xml/ops_merge_data2.xml').then(function(data) {
$scope.keyaccounts = data;
console.log($scope.keyaccounts);
});
}]);

Problems using $http inside a Service

I have a basic data Service which will be used across Controllers. But I'm having an issue grabbing some data that's been added via $http.
Service:
angular.module('core').service('FormService', ['$http', function($http) {
var _this = this;
_this.dropdownData = {
contactTimes: ['Anytime','Morning','Afternoon','Evening'],
industries: {},
};
$http.get('/json').success(function(resp){
_this.dropdownData.industries = resp.industries;
});
}]);
Controller:
angular.module('core').controller('SignupController', ['$scope', '$http', '$state', 'FormService', function($scope, $http, $state, FormService) {
console.log(FormService.dropdownData); // Shows full object incl industries
console.log(FormService.dropdownData.industries); // empty object {}
}]);
How do I get FormService.dropdownData.industries in my controller?
Create a service like below
appService.factory('Service', function ($http) {
return {
getIndustries: function () {
return $http.get('/json').then(function (response) {
return response.data;
});
}
}
});
Call in controller
appCtrl.controller('personalMsgCtrl', ['$scope', 'Service', function ($scope, Service) {
$scope.Industries = Service.getIndustries();
}]);
Hope this will help
Add a method to your service and use $Http.get inside that like below
_this.getindustries = function (callback) {
return $http.get('/json').success(function(resp){
_this.dropdownData.industries = resp.industries;
callback(_this.dropdownData)
});
};
In your controller need to access it like below.
angular.module('core').controller('myController', ['$scope', 'FormService', function ($scope, FormService) {
FormService.getDropdownData(function (dropdownData) {
console.log(dropdownData); // Shows full object incl industries
console.log(dropdownData.industries); // object {}
});
} ]);
Given that your console log shows the correct object, that shows your service is functioning properly. Only one small mistake you have made here. You need to access the data attributes in your return promise.
angular.module('core').service('FormService', ['$http', function($http) {
var _this = this;
_this.dropdownData = {
contactTimes: ['Anytime','Morning','Afternoon','Evening'],
industries: {},
};
$http.get('/json').success(function(resp){
//note that this is resp.data.industries, NOT resp.industries
_this.dropdownData.industries = resp.data.industries;
});
}]);
Assuming that you're data is indeed existing and there are no problems with the server, there are quite a few possible solutions
Returning a promise
angular.module('core').service('FormService', ['$http', function($http) {
var _this = this;
_this.dropdownData = {
contactTimes: ['Anytime','Morning','Afternoon','Evening'],
industries: {},
};
_this.dropdownData.industries = $http.get('/json');
}]);
//Controller
FormService.industries
.then(function(res){
$scope.industries = res.industries
});
Resolving with routeProvider / ui-route
See: $http request before AngularJS app initialises?
You could also write a function to initialize the service when the application starts running. At the end of the day, it is about waiting for the data to be loaded by using a promise. If you never heard about promises before, inform yourself first.
The industries object will be populated at a later point in time when the $http call returns. In the meantime you can still bind to the reference in your view because you've preserved the reference using angular.copy. When the $http call returns, the view will automatically be updated.
It is also a good idea to allow users of your service to handle the event when the $http call returns. You can do this by saving the $promise object as a property of industries:
angular.module('core').service('FormService', ['$http', function($http) {
var _this = this;
_this.dropdownData = {
contactTimes: ['Anytime','Morning','Afternoon','Evening'],
industries: {},
};
_this.dropdownData.industries.$promise = $http.get('/json').then(function(resp){
// when the ansyc call returns, populate the object,
// but preserve the reference
angular.copy( resp.data.industries, _this.dropdownData.industries);
return _this.dropdownData.industries;
});
}]);
Controller
app.controller('ctrl', function($scope, FormService){
// you can bind this to the view, even though the $http call has not returned yet
// the view will update automatically since the reference was preserved
$scope.dropdownData = FormService.dropdownData;
// alternatively, you can hook into the $http call back through the $promise
FormService.dropdownData.industries.$promise.success(function(industries) {
console.log(industries);
});
});

AngularJS factory not working

I have abstracted my working code from a controller into a factory, but it doesn't seem to be working and I can't find what's wrong. I opted for a factory rather than a service because I wanted to execute some code that defined the variable before returning that variable; I want to get result.station (a part of the data returned by the API), not the full result.
This is my code:
var app = angular.module("myApp", []);
app.factory('api', ['$http',
function($http) {
var station_list = [];
$http({
method: 'GET',
url: 'http://api.irail.be/stations/?format=json&lang=nl'
})
.success(function(result) {
station_list = result.station;
});
return {
Stations: function() {
return station_list;
}
};
}
]);
app.controller("myController", ['api', '$scope',
function(api, $scope) {
$scope.station_list = api.Stations();
$scope.title = "Stations";
}
]);
and a working example.
Try this:
.success(function(result) {
angular.copy(result.station, station_list);
});
You had a small error, you were replacing the array instead of populating it. I used angular.copy instead of the assignment in your factory and it works
http://plnkr.co/edit/sqgKcFZAcClmkfdXHhrz
The problem is that you are dealing with asynchronous nature of AJAX.
I would suggest to have a delegate method in controller, which will be called when the service call is complete.
Something like the following:
app.controller("myController", ['api', '$scope',
function(api, $scope) {
api.Stations( function(station_list) {
$scope.station_list = station_list;
});
$scope.title = "Stations";
}
]);
The following is a service method excerpt:
return {
Stations: function(delegate) {
if (delegate)
delegate(station_list);
return station_list;
}
};

Resources