As a newcomer to AngularJS, I aim to develop an application in adherence to John Papa's AngularJS style guide. To familiarize myself with these best practices, I have opted for the HotTowel skeleton.
My application requires consuming an HTTP API endpoint that fetches information about the authenticated user from example.com/api/users/me
. Since multiple controllers will use this data, I need a shared data service. A crucial prerequisite is that the API should only be called once. To achieve this, I created a method to initialize the service with a single API call. Drawing inspiration from HotTowel's core/dataservice.js
, my service script looks like this:
//File: currentUserDataService.js
(function() {
'use strict';
angular
.module('app.core')
.factory('currentUserDataService', currentUserDataService);
currentUserDataService.$inject = ['$http', '$q', 'exception', 'logger', 'config'];
/* @ngInject */
function currentUserDataService($http, $q, exception, logger, config) {
var user = {};
var service = {
init: init,
getData: getData
};
return service;
function getData(){
return user;
}
function init() {
return $http.get(config.apiBaseUrl + '/users/me')
.then(success)
.catch(fail);
function success(response) {
console.log(response.data);
user = response.data.data;
}
function fail(e) {
console.log(e);
return exception.catcher('XHR Failed for getPeople')(e);
}
}
}
})();
Next, I plan to utilize this service in the existing DashboardController
and ShellController
. The initial step involves configuring the dashboard route to resolve the promise of my service:
//File: dashboard.route.js
(function() {
'use strict';
angular
.module('app.dashboard')
.run(appRun);
appRun.$inject = ['routerHelper','currentUserDataService'];
/* @ngInject */
function appRun(routerHelper,currentUserDataService) {
routerHelper.configureStates(getStates(currentUserDataService));
}
function getStates(currentUserDataService) {
return [
{
state: 'dashboard',
config: {
url: '/',
templateUrl: 'app/dashboard/dashboard.html',
controller: 'DashboardController',
controllerAs: 'vm',
title: 'dashboard',
settings: {
nav: 1,
content: '<i class="fa fa-dashboard"></i> Dashboard'
},
resolve: {
'currentUserDataService': function(currentUserDataService){
return currentUserDataService.init;
}
}
}
}
];
}
})();
It is my understanding that I can now retrieve data using the getData
function of the service within my controller:
//File dashboad.controller.js
(function() {
'use strict';
angular
.module('app.dashboard')
.controller('DashboardController', DashboardController);
DashboardController.$inject = ['$q', 'currentUserDataService', 'logger'];
/* @ngInject */
function DashboardController($q, currentUserDataService, logger) {
var vm = this;
vm.user = {};
vm.title = 'Dashboard';
vm.getFullName = getFullName;
activate();
function activate() {
getCurrentUser();
logger.info('Activated Dashboard View');
}
function getCurrentUser() {
console.log(currentUserDataService);
//Interestingly I only get the init() function logged on the console
vm.user = currentUserDataService.getData(); //It fails here
console.log(vm.user);
return vm.user;
}
function getFullName(){
return vm.user.name + ' ' + vm.user.lastName;
}
}
})();
Upon running the application, I encounter the following error:
Error: currentUserDataService.getData is not a function
getCurrentUser@http://localhost:3000/src/client/app/dashboard/dashboard.controller.js:33:14
activate@http://localhost:3000/src/client/app/dashboard/dashboard.controller.js:24:4
DashboardController@http://localhost:3000/src/client/app/dashboard/dashboard.controller.js:21:3
instantiate@http://localhost:3000/bower_components/angular/angular.js:4640:14
$controller@http://localhost:3000/bower_components/angular/angular.js:10042:18
$ViewDirectiveFill/<.compile/<@http://localhost:3000/bower_components/angular-ui-router/release/angular-ui-router.js:4081:28
invokeLinkFn@http://localhost:3000/bower_components/angular/angular.js:9623:9
nodeLinkFn@http://localhost:3000/bower_components/angular/angular.js:9022:11
compositeLinkFn@http://localhost:3000/bower_components/angular/angular.js:8333:13
publicLinkFn@http://localhost:3000/bower_components/angular/angular.js:8213:30
lazyCompilation@http://localhost:3000/bower_components/angular/angular.js:8551:16
...
From experimenting with @DanEEStar's solution, another error has surfaced:
Error: [ ] currentUserDataService is undefined
getCurrentUser@http://localhost:3000/src/client/app/dashboard/dashboard.controller.js:33:4
...
The returned object from my service seems to lack other methods besides init. What could possibly be wrong with my code?