AngularJS encounters failure during shared data service initialization

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?

Answer №1

Make sure to call the init method in the resolve part of your state, rather than simply accessing it:

resolve: {
    'initData': function(currentUserDataService){
        // An issue may arise if you do not call the init method here
        return currentUserDataService.init();
    }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Preserve jQuery-enhanced webpage changes permanently

I am looking to permanently save modifications made on an HTML page using JQuery. I have come across suggestions about achieving this by sending an Ajax call and storing the data in a database table. However, I am unsure about what exactly needs to be save ...

Master the Art of Crafting Unique URLs

I am developing a web page that requires me to call two queries, each requiring an ID. However, I'm unsure of the best way to pass these IDs in the URL. For instance, one query is for books and the other is for authors. Currently, I have considered tw ...

Incorporating new elements onto the page without causing the existing elements to re-render

My challenge involves working with a large array of objects, where each object corresponds to one element. To display these elements on the page, I utilize the map() function, but currently only the first 5 elements are being rendered initially. In order t ...

Omit specific TagNames from the selection

How can I exclude <BR> elements when using the statement below? var children = document.getElementById('id').getElementsByTagName('*'); Is there a special syntax for getElementsByTagName that allows me to achieve this, or is the ...

What steps can I take to resolve a Bootstrap form validation issue where the email field is causing the label to shift down?

I am currently troubleshooting an issue in a website using Visual Studio, which is built with VB.NET, ASP.NET, HTML, CSS, and Bootstrap. The problem lies in the input validation under the email addresses. While one validation is working fine, the validatio ...

What is the best way to assign a variable with the type (x:number)=>{y:number,z:number}?

I am trying to initialize a variable called foo, but my current code is not compiling successfully. let foo: (x: number) => {y:number,z: number} = (x) => {x+1, x+2}; This results in the following error: Left side of comma operator is unused and ha ...

I'm puzzled as to why my Vuex modules are not functioning properly. I keep receiving the error message: "[vuex]

I've been searching for hours and can't figure out why I keep getting this error message: [vuex] unknown mutation type: groceryStore/getStoreApple on all of the commits to the mutations in the groceryStore-module. I believe I'm following the ...

Tips for eliminating additional white space within a bootstrap row

I'm having trouble removing the extra space on my website while using Bootstrap 5. I've tried various Bootstrap classes like pr-0, mr-0, p-auto, m-auto but none of them seem to work. I also attempted using CSS margin-right: 0; but that didn' ...

Updating every occurrence of a string in the visible text of a webpage: A step-by-step guide

I need to include the registered trademark symbol beside all mentions of a brand, which I'll refer to as "SomeBrand", on a client's website. Here is my current approach: function updateSomeBrand(){ var elements = document.getElementsByTagName( ...

Unable to change the background color of h1 tag in a ReactJS project

import React from 'react' export default function Home(){ return<div> <h1 className="bg-dark text-white p-3">Home Page</h1> </div> } I am attempting to modify the background color of the h1 tag in my Reac ...

The x-axis title in Apexcharts is consistently misaligned

Dealing with some issues regarding the placement of the x-axis title in my column chart. The position of the title seems to vary based on the y-values range, as illustrated in these examples: Example 1 Example 2 Below is the code I am using: Code block ...

There appears to be an issue with Google Analytics not generating __utm.gif requests, yet no error messages are

I'm encountering an issue with implementing Google Analytics. Despite extensive research, I haven't been able to find a resolution. My objective is to include the user's email address as a custom variable in Google Analytics. I have integra ...

How can I compare the current page URL with the navigation bar?

Looking to compare the URL of a current page to an element in the navigation bar using jQuery. Started by assigning the current URL to a variable: var currentPage = window.location.href; Then utilized an .each function to loop through each item in the n ...

The argument supplied to the `openUri()` function should be in the form of a string, but instead, it is displaying as "undefined". Please ensure that the initial parameter provided to either `mongoose.connect()`

Encountered error: The `uri` parameter passed to `openUri()` must be a string, but it is currently set as "undefined". Please ensure that the first parameter in either `mongoose.connect()` or `mongoose.createConnection()` is a valid string. Below are the ...

Using the JavaScript selectionchange event to target a specific element exclusively

I am looking for a way to incorporate a JavaScript selectionchange event on a specific div element. The goal is to display a highlighter box when the user selects text from the DOM. I was able to achieve this functionality for web using an onmouseup event, ...

Using an npm package in client-side JavaScript

I've been exploring client-side GitHub packages recently and came across developers mentioning that the packages can be downloaded using npm. This confuses me as I thought these were client-side JavaScript packages. They also mentioned something about ...

When the condition fails to activate

I am encountering an issue with my code that involves an if statement checking the value of a variable and binding a mousewheel event based on its true or false value. The problem is, the if condition only triggers on load and not when the value changes to ...

Issue with CSS: Dropdown menu is hidden behind carousel while hovering

I'm struggling with adjusting the position of my dropdown list. It keeps hiding behind the carousel (slider). When I set the position of the carousel section to absolute, it causes the navbar to become transparent and the images from the carousel show ...

What steps should I take to make index.html the default page on my http server?

I have set up an AngularJS application in a Node environment. I am using the http-server module to serve the files to the browser. Despite everything working smoothly, I'm struggling to make index.html the default file when the server launches. I hav ...

Unusual predicament encountered while using Flow type validation

I've encountered a puzzling situation in my React app while trying to integrate Flow's typechecking. I'm struggling to make everything work smoothly. Here is the relevant code snippet: // @flow export const UPDATE_SESSION_PROP: string = &ap ...