简体   繁体   English

角状态解析未注入控制器

[英]Angular state resolve not injecting into controller

I'm trying to get ui-router's resolve to pass its value to the controller portalsForUserCtrl . 我正在尝试获取ui路由器的portalsForUserCtrl以将其值传递给控制器portalsForUserCtrl

Here is the router: 这是路由器:

(function () {
'use strict';

var myApp = angular.module("myApp", ["common.services", "ui.router", 'ngMessages']);

    myApp.config(["$stateProvider", "$urlRouterProvider",
    function ($stateProvider, $urlRouterProvider) {
        $urlRouterProvider.otherwise("/");

        $stateProvider
            .state("portalsForUser", {
                url: "/userPortal/portalsForUser/:id",
                templateUrl: "app/userPortal/portalsForUser.html",
                controller: "portalsForUserCtrl as vm",
                resolve: {
                    userPortalService: "userPortalService",
                    portalsForUser: function (userPortalService, $stateParams) {
                        var userId = $stateParams.id;
                        console.log(userId);  //shows userId correctly
                        return userPortalService.getPortalsForUserPromise(userId)
                            .then(function (response) {
                                var userPortals = response.data;
                                console.log("userPortals", userPortals); //shows portals
                                return userPortals;
                            });
                    }
                }
            })
    }]
);

Here is the entire controller: 这是整个控制器:

(function () {
"use strict";

angular.module("myApp")
  .controller("portalsForUserCtrl", portalsForUserCtrl);

  portalsForUserCtrl.$inject = ['portalsForUser', 'userPortalService'];

  function portalsForUserCtrl(portalsForUser, userPortalService) {
    console.log("in portalsForUserCtrl");
    var vm = this;
    vm.portalsForUser = portalsForUser;
    console.log(portalsForUser);
  }

}());

In mainCtrl, which is the controller for index.html, I call: 在mainCtrl(它是index.html的控制器)中,我调用:

$state.go("portalsForUser", ({ "id": userId }));

Here is the code for the view app/userPortal/portalsForUser.html: 以下是视图app / userPortal / portalsForUser.html的代码:

<div class="container">
    <table class="table table-condensed table-striped table-bordered">
    <tbody>
        <tr>
            <th class="col-md-2">&nbsp;</th>
            <th class="col-md-4">
                Portal Name
            </th>
        </tr>

        <tr ng-repeat="userPortal in vm.portalsForUser">
            <td>
                {{userPortal.portal.portalName}}
            </td>
            <td class="">
                <a class="btn btn-primary" ui-sref="goSomewhere({id: userPortal.portal.id})">
                    Go
                </a>
            </td>
        </tr>
    </tbody>
</table>

Here is the code for the userPortalService: 这是userPortalService的代码:

(function () {
"use strict";

angular.module("myApp")
    .service('userPortalService', userPortalService);

userPortalService.$inject = ['userPortalResource', '$http', 'appSettings']

  function userPortalService(userPortalResource, $http, appSettings) {

    var getPortalsForUserPromise = function (id) {
        return $http.get(appSettings.serverPath + '/api/UserPortal/GetPortalsForUser/' + id);
    };

    return {
        getPortalsForUserPromise: getPortalsForUserPromise
    };
  }

}());

The url changes to the correct /userPortal/portalsForUser/:id but the portalsForUserCtrl function does not fire. URL更改为正确的/userPortal/portalsForUser/:idportalsForUserCtrl函数不会触发。 It is only when I hit enter on the same url that portalsForUserCtrl is instantiated and the data appears in the view. 只有在我在相同的URL上按回车时,才会实例化portalsForUserCtrl并在视图中显示数据。 What am I missing? 我想念什么?

You have a syntax error in the $state.go statement. $ state.go语句中有语法错误。

Change this: 更改此:

$state.go("portalsForUser", ({ "id": userId })); .

to this: 对此:

$state.go("portalsForUser", { "id": userId });

There might be an issue with dependency injection. 依赖项注入可能存在问题。 Try this - 尝试这个 -

resolve: {
           portalsForUser: ['userPortalService', '$stateParams', function (userPortalService, $stateParams) {
           var userId = $stateParams.id;
                 return userPortalService.getPortalsForUserPromise(userId)
                        .then(function (response) {
                            var userPortals = response.data;
                            console.log("userPortals", userPortals);
                            return userPortals;
                        });
                }] 
          }

On the documentation ( https://angular-ui.github.io/ui-router/site/#/api/ui.router.state .$stateProvider) the specification of the method mentions the following: 在文档( https://angular-ui.github.io/ui-router/site/#/api/ui.router.state。$ stateProvider)上,该方法的规范提到以下内容:

The map object is: 地图对象是:

key - {string}: name of dependency to be injected into controller factory - {string|function}: If string then it is alias for service. 键-{string}:要注入控制器工厂的依赖项的名称-{string | function}:如果为string,则它是服务的别名。 Otherwise if function, it is injected and return value it treated as dependency. 否则如果是函数,则将其注入并返回将其视为依赖项的值。 If result is a promise, it is resolved before its value is injected into controller. 如果结果是承诺,则在将其值注入控制器之前将其解析。

with the following as an example: 以以下为例:

resolve: {
    myResolve1:
        function($http, $stateParams) {
          return $http.get("/api/foos/"+stateParams.fooID);
        }
    }

So I suggest you change your code into one of these options to make it as simple a possible and, using chrome developer tool, place a breakpoint on the first line on the method: 因此,我建议您将代码更改为以下选项之一,以使其尽可能简单,并使用chrome开发人员工具,在该方法的第一行上放置一个断点:

resolve: {
    portalsForUser: ['userPortalService', '$stateParams', function (userPortalService, $stateParams) {
        var userId = $stateParams.id; //place your breakpoint here
        return userPortalService.getPortalsForUserPromise(userId);
    }] 
}

Check what is going on with $stateParams; 用$ stateParams检查发生了什么; it is not impossible that, for some reason, at this moment, everything is not initialized yet because values don't come from the url, therefore, the id property is undefined. 由于某种原因,由于当前值并非来自url,因此由于某种原因,目前还没有全部初始化是不可能的,因此id属性是未定义的。 Try to inject "$state" and see if $state.params.id contains what you expect instead. 尝试注入“ $ state”,然后查看$ state.params.id是否包含您期望的内容。 (like mentioned in here: https://angular-ui.github.io/ui-router/site/#/api/ui.router.state .$state). (如此处所述: https//angular-ui.github.io/ui-router/site/#/api/ui.router.state。$ state)。 Here is what it could look like: 看起来像这样:

resolve: {
    portalsForUser: ['userPortalService', '$state', function (userPortalService, $state) {
        var userId = $state.params.id; //place your breakpoint here
        return userPortalService.getPortalsForUserPromise(userId);
    }] 
}

Hope that if it doesn't solve your problem, at least it will help you to find it. 希望它不能解决您的问题,至少可以帮助您找到它。

EDIT: 编辑:

It seems all the previous doesn't go to the right direction. 似乎所有以前的方法都不正确。

Here is my new direction: I used your plunker to create a hosted site on my computer (using http-server: https://www.npmjs.com/package/http-server ). 这是我的新方向:我使用您的窃听器在计算机上创建了一个托管站点(使用http-server: https ://www.npmjs.com/package/http-server)。 My version that doesn't seem to be very different than yours works perfectly. 我的版本似乎与您的版本没有太大不同,但效果很好。 Here is the full code: 这是完整的代码:

app.js: app.js:

(function () {
    'use strict';

    var myApp = angular.module("myApp", ["ui.router"]);

    myApp
        .config(config)
        .controller("portalsForUserCtrl", portalsForUserCtrl)
        .service('userPortalService', userPortalService)
        .controller("mainCtrl", mainCtrl)

    mainCtrl.$inject = ["userPortalService", "$state"];

    function mainCtrl(userPortalService, $state) {
        var vm = this;

        vm.clickMe = function () {
          var userId = 1;
            $state.go("portalsForUser", { "id": userId });
        }
    };

    config.$inject=["$stateProvider"];

    function config($stateProvider) {
            $stateProvider
                // PortalsForUser GET
                .state("portalsForUser", {
                    url: "/userPortal/portalsForUser/:id",
                    templateUrl: "portalsForUser.html",
                    controller: "portalsForUserCtrl as vm",
                    resolve: {
                        portalsForUser: ['userPortalService', '$stateParams', function (userPortalService, $stateParams) {
                            return userPortalService.getPortalsForUserPromise($stateParams.id).then(function(response){return response.data;});
                        }]
                    }
                })
        }

    userPortalService.$inject = ['$http', '$q', '$timeout']

    function userPortalService($http, $q, $timeout) {
        var getPortalsForUserPromise = function (id) {
            var myId=id;
            var deferred=$q.defer();

            $timeout(function(){
                deferred.resolve({data:[
                    {
                    id: 16,
                    portal: {
                        portalName: "Portal1-" + myId,
                        portalId: 1
                    }
                    },
                    {
                    id: 17,
                    portal: {
                        portalName: "Portal2-" + myId,
                        portalId: 2
                    }
                    }
                ]});
            },5000);
            return deferred.promise;
        };

        return {
            getPortalsForUserPromise: getPortalsForUserPromise
        };
    };

    portalsForUserCtrl.$inject = ['portalsForUser', 'userPortalService'];

    function portalsForUserCtrl(portalsForUser, userPortalService) {
        console.log("in portalsForUserCtrl");
        var vm = this;
        vm.portalsForUser = portalsForUser;
        console.log(portalsForUser);
    };
}());

index.html: index.html:

<html>
    <head></head>
</html>
<body ng-app="myApp">
    <!-- bower:js -->
    <script src="/bower_components/angular/angular.js"></script>
    <script src="/bower_components/angular-ui-router/release/angular-ui-router.js"></script>
    <!-- endbower -->

    <!-- inject:js -->
    <script src="app.js"></script>
    <!-- endinject -->
    <body ng-app="myApp" ng-controller="mainCtrl as vm">
        <button type="submit" class="btn btn-default" ng-click="vm.clickMe()">
            Click Me
        </button>
        <div ui-view></div>
    </body>
</body>

portalsForUser.html: portalsForUser.html:

<div class="container">
    Portals For User
    <table class="table table-condensed table-striped table-bordered">
        <tbody>
            <tr>
                <th class="col-md-2">&nbsp;</th>
                <th class="col-md-4">
                    Portal Name
                </th>
            </tr>

            <tr ng-repeat="userPortal in vm.portalsForUser">
                <td>
                    {{userPortal.portal.portalName}}
                </td>
                <td class="">
                    <a class="btn btn-primary" ui-sref="goSomewhere({id: userPortal.portal.id})">
                        Go
                    </a>
                </td>
            </tr>
        </tbody>
    </table>

</div>

bower.json bower.json

{
  "name": "test",
  "description": "just a test",
  "main": "index.js",
  "authors": [
    "me"
  ],
  "license": "ISC",
  "homepage": "index.html",
  "private": true,
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ],
  "dependencies": {
    "angular": "^1.5.8",
    "angular-ui-router": "ui-router#^0.3.1"
  }
}

I added the div ui-view in index.html like suggested by somebody else, but I believe this was already in your initial project. 我像其他人建议的那样在index.html中添加了div ui-view,但是我相信这已经在您的初始项目中了。 I also tried to simulate the service like the real one would work (with a promise and with a property data). 我还试图模拟服务,就像真正的服务一样工作(带有承诺和属性数据)。

Are you sure you have correct versions of ui-router and angular? 您确定自己的ui-router和angular版本正确吗?

Based in your code, I've seen that the your controller it's associated to the module clubSkedApp and your config it's associated to the myApp module. 根据您的代码,我已经看到您的控制器已与模块clubSkedApp关联,而您的配置已与myApp模块关联。

Use the same module for both, or include the module of your controller like this. 两者都使用相同的模块,或者像这样包含控制器的模块。

var myApp = angular.module("myApp", ["clubSkedApp","common.services", "ui.router", 'ngMessages']);

Another approach is check why the state it's not loaded. 另一种方法是检查为什么未加载状态。 Ui-router isn't good to raise errors, the only way that i find to check the errors in a route's change is the following: UI路由器不好引发错误,我发现检查路由更改中的错误的唯一方法是:

myApp.run(runFn);

runFn.$inject = ['$rootScope'];

function runFn($rootScope){

  //Show the errores caused by the resolve function
  $rootScope.$on('$stateChangeError', function (event, toState, toParams, 
    fromState, fromParams, error) {
      event.preventDefault();
      console.log(error);
    });
}

I know the problem. 我知道这个问题。 The solution is very simple. 解决方案非常简单。

You need to add <div ui-view></div> into index.html to display your view in the later state like below code. 您需要将<div ui-view></div>index.html中 ,以便在以后的状态下显示您的视图,如下面的代码所示。

  <body ng-app="myApp" ng-controller="mainCtrl as vm">
    <button type="submit" class="btn btn-default" ng-click="vm.clickMe()">
        Click Me
    </button>
    <div ui-view></div>
  </body>

For more detail 欲了解更多信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM