1

I'm following John Papa's angular style guide (https://github.com/johnpapa/angular-styleguide#routing) and using a custom wrapper around the angular ui-router provided in this guide. However, the wrapper does not work for me and I get a circular dependency error when injecting $state:

Uncaught Error: [$injector:cdep] Circular dependency found: $rootScope <- $timeout <- $$rAF <- $$animateQueue <- $animate <- toastr <- logger <- $exceptionHandler <- $rootScope <- $state <- routerHelper

I have tried injecting $state manually using $injector but that gives me an unknown provider error.

Here is the code:

(function() {
'use strict';

angular
    .module('blocks.router')
    .provider('routerHelper', routerHelperProvider);

routerHelperProvider.$inject = ['$locationProvider', '$stateProvider', '$urlRouterProvider', '$injector'];

function routerHelperProvider($locationProvider, $stateProvider, $urlRouterProvider) {


    this.$get = RouterHelper;

    $locationProvider.html5Mode(true);

    RouterHelper.$inject = ['$state'];

    function RouterHelper($state) {
        var hasOtherwise = false;

        var service = {
            configureStates: configureStates,
            getStates: getStates
        };

        return service;

        function configureStates(states, otherwisePath) {
            states.forEach(function (state) {
                $stateProvider.state(state.state, state.config);
            });
            if (otherwisePath && !hasOtherwise) {
                hasOtherwise = true;
                $urlRouterProvider.otherwise(otherwisePath);
            }
        }

        function getStates() {
            return $state.get();
        }
    }

}
})(); 

1 Answer 1

3

I think this is a problem with toastr and not the UI router code.

John Papa bases his examples off the plain 'toastr' package and not the 'angular-toastr' package.

toastr: https://github.com/CodeSeven/toastr

angular-toastr: https://github.com/Foxandxss/angular-toastr

With the 'toastr' package he registers the global instance of toastr using a constant:

    .module('app.core')
    .constant('toastr', toastr);

Which makes it available for injection into the logger service:

logger.$inject = ['$log', 'toastr'];

/* @ngInject */
function logger($log, toastr) {

However if you use the angular-toastr package, the toastr object introduces a set of dependencies upon some angular objects:

$rootScope <- $timeout <- $$rAF <- $$animateQueue <- $animate <- toastr

And this causes a circular dependency because the $rootScope has exception handling which uses the logger/toastr objects:

toastr <- logger <- $exceptionHandler <- $rootScope

I wasn't sure how to properly refactor this to remove the circular dependency. So as a temporary workaround, I changed the logger service to delay resolution of the toastr dependency using $injector. Not ideal, but I was able to move on to other pressing concerns.

logger.$inject = ['$log', '$injector']; // 'toastr'

/* @ngInject */
function logger($log, $injector) { // toastr

    var service = {
        showToasts: true,

        info    : info,
        success : success,
        warning : warning,
        error   : error,

        // straight to console; bypass toastr
        log     : $log.log
    };

    return service;
    /////////////////////


    function info(message, data, title) {
        var toastr = $injector.get('toastr');

        toastr.info(message, title);
        $log.info('Info: ' + message, data);
    }

    function success(message, data, title) {
        var toastr = $injector.get('toastr');

        toastr.success(message, title);
        $log.info('Success: ' + message, data);
    }

    function warning(message, data, title) {
        var toastr = $injector.get('toastr');

        toastr.warning(message, title);
        $log.warn('Warning: ' + message, data);
    }

    function error(message, data, title) {
        var toastr = $injector.get('toastr');

        toastr.error(message, title);
        $log.error('Error: ' + message, data);
    }

}
Sign up to request clarification or add additional context in comments.

1 Comment

encountered same issue when trying to use angular-toastr on HotTowel template. Delaying the dependency using $inject worked for me. As @Casey said, not sure whether thats the correct way.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.