AngularJS + Routing + Resolve

自古美人都是妖i 提交于 2019-12-30 11:29:10

问题


I'm getting this error:

Error: Error: [$injector:unpr] http://errors.angularjs.org/1.3.7/$injector/unpr?p0=HttpResponseProvider%20%3C-%20HttpResponse%20%3C-%20DealerLeads

Injector Unknown provider

Here's my router (ui.router):

$stateProvider
        .state('main', {
            url: "/main",
            templateUrl: "views/main.html",
            data: { pageTitle: 'Main Page' }
        })
        .state('leads', {
            url: "/leads",
            templateUrl: "views/leads.html",
            data: { pageTitle: 'Dealer Leads' },
            controller: 'DealerLeads',
            resolve: DealerLeads.resolve
        })

Here's my Controller:

function DealerLeads($scope, HttpResponse) {
    alert(JSON.stringify(HttpResponse));
}

Here's my resolve:

DealerLeads.resolve = {
    HttpResponse: function ($http) {
...
    }
}

The data is getting to the controller, I see it in the alert. However, after the controller is done, during the rendering of the view (I think), the issue seems to be happening.

The final rendered view has two controllers: One main controller in the body tag, and the second controller 'DealerLeads' inside of that. I've tried removing the main controller, and the issue is still present.

What am I doing wrong? Is there any more code that is necessary to understand/resolve the issue?


回答1:


When you use route resolve argument as dependency injection in the controller bound to the route, you cannot use that controller with ng-controller directive because the service provider with the name HttpResponse 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.

Just remove the ng-controller="DealerLeads" from the view and make sure that view is part of the html rendered by the state leads @ templateUrl: "views/leads.html",. Router will bind it to the the template for you resolving the dynamic dependency HttpResponse. If you want to use controllerAs you can specify that in the router itself as:-

controller: 'DealerLeads',
controllerAs: 'leads' //Not sure if this is supported by ui router yet

or

controller: 'DealerLeads as leads',

Also when you do:

.state('leads', {
        url: "/leads",
        templateUrl: "views/leads.html",
        data: { pageTitle: 'Dealer Leads' },
        controller: 'DealerLeads',
        resolve: DealerLeads.resolve
    })

make sure that DealerLeads is accessible at the place where the route is defined. It would be a better practice to move the route definition to its own controller file so that they are all in one place. And whenever possible especially in a partial view of a route it is better to get rid of ng-controller starting the directive and instead use route to instantiate and bind the controller for that template. It gives more re-usability in terms of the view as a whole not being tightly coupled with a controller name and instead only with its contract. So i would not worry about removing ng-controller directive where router can instantiate the controller.




回答2:


I'm not completely understand you question, and also not an expert as @PSL in angular.

If you just want to pass some data into the controller, maybe below code can help you.

I copied a piece of code from the project:

.state('masthead.loadTests.test',{
    url: '/loadTests/:id',
    templateUrl: 'load-tests/templates/load-test-entity.tpl.html',
    controller: 'loadTestEntityCtrl',
    data: { pageTitle: 'loadTests',
        csh: '1005'
    },
    resolve: {
        // Get test entity data before enter to the page (need to know running state)
        LoadTestEntityData: [
            '$stateParams',
            '$state',
            'LoadTestEntity',
            'LoggerService',
            '$rootScope',
            function ($stateParams, $state, LoadTestEntity, LoggerService, $rootScope) {
                // Get general data
                return LoadTestEntity.get({id: $stateParams.id},function () {
                },
                    // Fail
                    function () {
                        // When error navigate to homepage
                        LoggerService.error('error during test initiation');
                        $state.go('masthead.loadTests.list', {TENANTID: $rootScope.session.tenantId});
                    }).$promise;
            }
        ]
    }
})

Here the LoadTestEntityData is the data we injected into the controller, LoadTestEntity and LoggerService are services needed for building the data.

.factory('LoadTestEntity', ['$resource', function ($resource) {
    return $resource(
        '/api/xxx/:id',
        {id: '@id'},
        {
            create: {method: 'POST'},
            update: {method: 'PUT'}
        }
    );
}])

Hope it helps!



来源:https://stackoverflow.com/questions/28205914/angularjs-routing-resolve

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!