角状态决定不注入控制器

时间:2016-09-21 22:38:29

标签: javascript angularjs angular-ui-router

我试图让ui-router决定将其值传递给控制器​​portalsForUserCtrl

这是路由器:

(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;
                            });
                    }
                }
            })
    }]
);

这是整个控制器:

(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);
  }

}());

在mainCtrl中,它是index.html的控制器,我调用:

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

以下是视图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>

以下是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
    };
  }

}());

网址更改为正确的/userPortal/portalsForUser/:id,但portalsForUserCtrl功能不会触发。 只有当我在同一个网址上输入时才会实例化portalsForUserCtrl并且数据会显示在视图中。我缺少什么?

5 个答案:

答案 0 :(得分:1)

$ state.go语句中存在语法错误。

改变这个:

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

到此:

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

答案 1 :(得分:0)

依赖注入可能存在问题。试试这个 -

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;
                        });
                }] 
          }

答案 2 :(得分:0)

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

  

地图对象是:

     

key - {string}:要注入控制器的依赖项名称   factory - {string | function}:如果是string,那么它就是service的别名。   否则,如果是函数,则将其注入并将其视为返回值   依赖。如果result是promise,则在其值之前解析   注入控制器。

以下面的例子为例:

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

因此,我建议您将代码更改为其中一个选项,以使其尽可能简单,并使用chrome开发人员工具在方法的第一行放置一个断点:

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

检查$ stateParams发生了什么;由于某种原因,在某个时候,一切都没有被初始化,因为价值观不是来自网址,因此,id属性是不确定的。尝试注入&#34; $ state&#34;并查看$ state.params.id是否包含您期望的内容。 (如此处所述:https://angular-ui.github.io/ui-router/site/#/api/ui.router.state。$ state)。 这是它的样子:

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

希望如果它没有解决您的问题,至少它会帮助您找到它。

修改

以前所有人都没有朝着正确的方向前进。

这是我的新方向: 我用你的plunker在我的电脑上创建一个托管网站(使用http-server:https://www.npmjs.com/package/http-server)。我的版本似乎与你的版本完全不同。这是完整的代码:

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:

<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:

<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

{
  "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"
  }
}

我在index.html中添加了div ui-view,就像其他人建议的那样,但我相信这已经在你的初始项目中了。 我也尝试模拟真实的服务(使用promise和属性数据)。

你确定你有正确版本的ui-router和angular吗?

答案 3 :(得分:0)

根据您的代码,我已经看到您的控制器与模块clubSkedApp相关联,而您的配置与myApp模块相关联。

对两者使用相同的模块,或者像这样包含控制器的模块。

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

另一种方法是检查未加载状态的原因。 Ui-router不会引发错误,我发现检查路由更改错误的唯一方法如下:

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);
    });
}

答案 4 :(得分:0)

我知道这个问题。解决方案非常简单。

您需要将<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>

了解更多详情