Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UI-Router and resolve, unknown provider in controller

I am using resolve in my UI-Router .state() call. In my controller I can access the values no problem, but it is throwing an error as follows:

$injector/unpr?p0=ctrlOptionsProvider%20%3C-trlOptions

The following code throws the error but allows me to access the variable ctrlOptions just fine:

.state('new_user', {
            url: "/user/new",
            templateUrl: "views/user/new.html",
            data: {pageTitle: 'New User'},
            controller: "UserController",
            resolve: {

                ctrlOptions: ['$stateParams', function($stateParams) {

                    return {

                        view: 'new_user',
                    }
                }],
                deps: ['$ocLazyLoad', function($ocLazyLoad) {
                    return $ocLazyLoad.load({ 
                        name: 'MetronicApp',  
                        insertBefore: '#ng_load_plugins_before', // load the above css files before '#ng_load_plugins_before'
                        files: [
                            '../../../assets/global/plugins/bootstrap-datepicker/css/datepicker3.css',
                            '../../../assets/global/plugins/select2/select2.css',

                            '../../../assets/global/plugins/bootstrap-datepicker/js/bootstrap-datepicker.js',
                            '../../../assets/global/plugins/select2/select2.min.js', 
                        ]                    
                    });
                }]
            }
        })

MetronicApp.controller('UserController', ['$rootScope', '$scope', '$http', '$stateParams', 'ctrlOptions', function($rootScope, $scope, $http, $stateParams, ctrlOptions, $timeout) {}

Any idea how to fix this?

Thanks

like image 836
jim Avatar asked Jan 27 '15 16:01

jim


2 Answers

Remove ng-controller="UserController" from your view, let the router instantiate the controller.

When you use route resolve argument as dependency injection in the controller bound to the route, you cannot use that controller with ng-controller/or any other directive because the service provider with the name ctrlOptions does not exist. It is a dynamic dependency that is injected by the router when it instantiates the controller to be bound in its respective partial view. It is also a better practice not to instantiate a controller with ng-controller and starting a template with ng-controller directive when router can instantiate and bind the controller to that template, template will be more reusable as it is not tightly coupled with the controller name (with ng-controller="ctrlName" ) but only with the contract.

like image 166
PSL Avatar answered Oct 31 '22 22:10

PSL


So I had the same problem but my setup is different. Just posting it in case anyone runs into it too. First time posting an answer so not sure if there's a better place to put an answer that doesn't solve the OP's answer but still solves a variant of the question asked.

App State

I have a parent state "app" and a child state "home". When a User logs in they go through the "app" state which did the resolving and then they get redirected to the "home" state.

angular
.module('common')
.component('app', {
    templateUrl: './app.html',
    controller: 'AppController',
    bindings: {
        member: '=',
        organization: '=',
    }
})
.config(function ($stateProvider) {
    $stateProvider
        .state('app', {
            redirectTo: 'home',
            url: '/app',
            data: {
                requiredAuth: true
            },
            resolve: {
                member: ['AuthService',
                    function (AuthService) {
                        return AuthService.identifyMember()
                            .then(function (res) {
                                AuthService.setAuthentication(true);
                                return res.data;
                            })
                            .catch(function () {
                               return null;
                            });
                    }
                ],
                organization: ['AuthService',
                    function (AuthService) {
                        return AuthService.identifyOrganization()
                            .then(function (res) {
                                return res.data;
                            })
                            .catch(function () {
                                return null;
                            });
                    }
                ],
                authenticated: function ($state, member) {
                    if (!member)
                        $state.go('auth.login');
                }
            },
            component: 'app',
        });
});

The solution for me was in the bindings. I had done it for member before but forgot to do it for organization so that was my silly problem.

Home State

angular
.module('components')
.component('home', {
    templateUrl: './home.html',
    controller: 'HomeController',
    bindings: {
        member: '=',
        organization: '=',
    }
})
.config(function ($stateProvider) {
    $stateProvider
    .state('home', {
        parent: 'app',
        url: '/home',
        data: {
            requiredAuth: true
        },
        component: 'home',
        resolve: {
            'title' : ['$rootScope',
                function ($rootScope) {
                    $rootScope.title = "Home";
                }
            ],
        }
    });
});

Again the solution was in the bindings.

NOTE: I did not have to inject the data into my controller

function HomeController(AuthService, $state) {
    let ctrl = this;
}

Not sure why I didn't have to inject directly into the controller for it to be available as ctrl.member and ctrl.organization.

like image 29
Chris Gala Avatar answered Oct 31 '22 22:10

Chris Gala