简体   繁体   English

AngularAMD + UI路由器多个视图不会加载控制器

[英]AngularAMD + ui-router multiple views does not load controllers

I'm trying to use angular-ui-router with angularAMD and there is one thing I cannot get working. 我正在尝试将angular-ui-router与angularAMD一起使用,有一件事我无法正常工作。

I have one abstract state (named "first") and another nested state (named "second") that inherits from "first" and that contains a views key with 2 views, each view having its own controller and template. 我有一个抽象状态(称为“第一个”)和另一个嵌套状态(名为“第二个”),该状态继承自“第一个”并且包含一个具有2个视图的视图键,每个视图都有其自己的控制器和模板。

On angularAMD repo (github.com/marcoslin/angularAMD/issues/62), marcoslin show a way to do that, but I can't make it work, thus I think it's not exactly my situation :( 在angularAMD仓库(github.com/marcoslin/angularAMD/issues/62)上,marcoslin显示了一种方法,但我无法使其正常工作,因此我认为这不完全是我的情况:(

$stateProvider
    .state('root', {
        url: '',
        abstract: true,
        views: {
            'header': angularAMD.route({
                templateUrl: 'app/root/header.tpl.html',
                controller: 'HeaderCtrl',
                controllerUrl: 'HeaderCtrl'
            }),
            'footer': angularAMD.route({
                templateUrl: 'app/root/footer.tpl.html',
                controller:'FooterCtrl',
                controllerUrl: 'FooterCtrl'
            })
        }
    })

I was converting some big project in a lazy load way, so I thought the problem could come from a still not found side-effect. 我正在以懒惰的方式转换一些大型项目,所以我认为问题可能出在尚未发现的副作用上。 I made a simple plunker to check if it works better in a simpler environment, but it still doesn't work. 我做了一个简单的调试器,以检查它在更简单的环境中是否可以更好地工作,但仍然无法正常工作。

Essentially, my problematic code is this one: 本质上,我的问题代码是这样的:

    $stateProvider
        .state('first',
            angularAMD.route({
                abstract: true,
                controllerUrl: 'first-controller',
                templateUrl: 'first.tmpl.html',
                controllerAs: 'first'
            })
        )
        .state('first.second', {
          url: '/introduction',
            views: {
                second1: angularAMD.route({
                    templateUrl: 'second1.tmpl.html',
                    controllerUrl: 'second1-controller',
                    controllerAs: 'second1'
                }),
                second2: angularAMD.route({
                    templateUrl: 'second2.tmpl.html',
                    controllerUrl: 'second2-controller',
                    controllerAs: 'second2'
                })
            }
        });

Please note that I use the possibility provided by angularAMD to avoid using controller key in angularAMD.route() method. 请注意,我使用angularAMD提供的可能性来避免在angularAMD.route()方法中使用控制器键。 You can do this if your controller file return an anonymous function. 如果控制器文件返回匿名函数,则可以执行此操作。

My full example can be found here: http://plnkr.co/edit/5WBtd3R7k20yRkMazIuk?p=preview 我的完整示例可以在这里找到: http : //plnkr.co/edit/5WBtd3R7k20yRkMazIuk?p=preview

EDIT: I've forked my Plunker to show what happens when I try to use the more traditionnal angular syntax, without returning an anonymous function when loading my controllers. 编辑:我已经分叉了我的Plunker,以显示当我尝试使用更传统的角度语法时会发生什么,而在加载控制器时不返回匿名函数。

So the controller looks like: 因此,控制器看起来像:

define(['app'], function (app) {
  'use strict';

  app.controller('Second1Controller', function () {
      var vm = this;

      vm.value = "Hello you ! I'm Number 2.1";
    });
});

and the call to angularAMD in the ui-router is changed like this (notice the controller key): 并且对ui路由器中对angularAMD的调用将如下更改(请注意控制器键):

.state('first.second', {
          url: '/introduction',
            views: {
                second1: angularAMD.route({
                    templateUrl: 'second1.tmpl.html',
                    controllerAs: 'second1',
                    controllerUrl: 'second1-controller',
                    controller: 'Second1Controller'
                }),
                second2: angularAMD.route({
                    templateUrl: 'second2.tmpl.html',
                    controllerUrl: 'second2-controller',
                    controllerAs: 'second2',
                    controller: 'Second2Controller'
                })
            }
        });

See the new Plunker here: http://plnkr.co/edit/kPFBo7ssAtqAuiKdwnQ9?p=preview 在此处查看新的Plunker: http ://plnkr.co/edit/kPFBo7ssAtqAuiKdwnQ9?p=preview

This time I get the usual error that fires when you have not loaded what you try to use: 这次,当您未加载尝试使用的内容时,我会触发通常的错误:

Error: [ng:areq] Argument 'Second1Controller' is not a function, got undefined 错误:[ng:areq]参数'Second1Controller'不是一个函数,未定义

END EDIT 结束编辑

Anybody to help me ? 有人帮我吗? :) :)

Cheers ! 干杯!

Joel 乔尔

How angularAMD Works angularAMD如何工作

angularAMD adds a promise to the ui-router native 'resolve' property of the state config object so that it looks somewhat like this: angularAMD向状态配置对象的ui路由器本机“ resolve”属性添加了一个承诺,使其看起来像这样:

$stateProvider.state('login', {
    url : '/login',
    controller : 'loginCtrl',
    resolve : {
        ...
    },
    views : {
        ...
    }
    ...
});

The promise is resolved when the script is loaded via RequireJS. 通过RequireJS加载脚本时,可以解决承诺。 Only after all promises of the resolve object are fulfilled will the controller be instantiated. 只有在解决对象的所有承诺都得到满足后,控制器才会实例化。 This is great since it allows lazy loading of scripts. 这很棒,因为它允许延迟加载脚本。

Why the Error is Thrown 为什么引发错误

The resolve property on the view is not interpreted by angular-ui-router. angular-ui-router不会解释视图上的resolve属性。 The JavaScript file containing the controller is not loaded at all. 完全不加载包含控制器的JavaScript文件。 Angular can therefore not find the function ('Second1Controller' is not a function, got undefined). 因此,Angular找不到函数(“ Second1Controller”不是函数,未定义)。

How to Adapt to Multiple Views 如何适应多种观点

While this works perfectly fine with regular (not nested) views, there are issues with nested views. 尽管这对于常规(非嵌套)视图非常有效,但是嵌套视图仍然存在问题。 The resolve object is not allowed on individual views but must be placed directly inside the state config (see Angular UI Router Docs ). 单独视图上不允许使用resolve对象,但必须将其直接放在状态配置中(请参阅Angular UI Router Docs )。 We thus somehow have to define the controllerUrls on the state config's highest level instead of on the individual view. 因此,我们必须以某种方式在状态配置的最高级别而不是在单个视图上定义controllerUrl。 This works with tiny changes in angularAMD and our config. 这可以在angularAMD和我们的配置中进行微小的更改。

// angularAMD.js around line 146

if (load_controller) {
   var resolve = config.resolve || {};
   resolve['__AAMDCtrl'] = ['$q', '$rootScope', function ($q, $rootScope) { // jshint ignore:line
       var defer = $q.defer();
       // NOTE: It is now possible to load an array of controllerUrl's.
       // Only the first array element will be injected as ctrl (room for improvement here)
       require(load_controller instanceof Array ? load_controller : [load_controller], function (ctrl) {
           defer.resolve(ctrl);
           //console.log('loaded ' + load_controller);
           $rootScope.$apply();
       });
       return defer.promise;
   }];
   config.resolve = resolve;
}

Our config must be changed, too: 我们的配置也必须更改:

$stateProvider.state('login', {
    url : '/login',
    controllerUrl : [
         'template1Ctrl.js',
         'template2Ctrl.js'
    ]
    views : {
        'viewContainer1' : {
            templateUrl   : 'template1.html',
            controller    : 'template1Ctrl'
        },
        'viewContainer2' : {
            templateUrl   : 'template2.html',
            controller    : 'template2Ctrl'
        }
    }
    ...
});

I was trying to use angularAMD a week or two ago for something similar, and figured out how to get it to load there. 我在一两个星期前试图使用angularAMD做类似的事情,并弄清楚如何将其加载到那里。 I went ahead and got your code working on plunkr. 我继续进行,让您的代码在plunkr上运行。

define([
  'angular',
  'angularAMD',
  'angular-ui-router',
  'second1-controller',
  'second2-controller',
  'first-controller'
], function (angular, angularAMD) {
  'use strict';

  var app = angular.module('myApp', ['ui.router'])
    .config(function ($stateProvider, $urlRouterProvider) {
      $stateProvider
        .state('first',
            angularAMD.route({
                abstract: true,
                controllerUrl: 'first-controller',
                templateUrl: 'first.tmpl.html',
                controller: 'first-controller'
            })
        )
        .state('first.second', {
          url: '/introduction',
            views: {
                second1: angularAMD.route({
                    templateUrl: 'second1.tmpl.html',
                    controllerUrl: 'second1-controller',
                    controller: 'second1-controller'
                }),
                second2: angularAMD.route({
                    templateUrl: 'second2.tmpl.html',
                    controllerUrl: 'second2-controller',
                    controller: 'second2-controller'
                })
            }
        });

      $urlRouterProvider.when('', '/introduction');
      $urlRouterProvider.when('/', '/introduction');
    });

    return angularAMD.bootstrap(app);
});

and setup the controllers as such: 并按如下方式设置控制器:

define(['angularAMD'], function (angularAMD) {
  'use strict';
  angularAMD.controller('first-controller',['$scope',function($scope){
    $scope.foo='bar';
  }]);
});

, http://plnkr.co/edit/bvaNDXhhelmo0smEDPWh?p=preview http://plnkr.co/edit/bvaNDXhhelmo0smEDPWh?p=preview

FYI with AngularAMD and using angular-ui-router (for those who may hit this via google trying to solve a problem - like me) 使用AngularAMD并使用angular-ui-router进行仅供参考(适用于可能通过Google尝试解决问题的人-像我一样)

I found that angular-ui-router Version v0.2.15 - does NOT work as intended with angularAMD 我发现,角UI路由器版本v0.2.15 -因为打算与angularAMD 不工作

When I downgraded to this version : //cdn.jsdelivr.net/angular.ui-router/0.2.12/angular-ui-router.min 当我降级到这个版本时 ://cdn.jsdelivr.net/angular.ui-router/0.2.12/angular-ui-router.min

Version 0.2.12 worked just fine and all that was lost was a good deal of sanity and time. 0.2.12版本工作得很好,而所有丢失的内容都是很多理智和时间。 BUT - still have to appreciate other people's work they give away for free. 但是-仍然必须欣赏他们免费提供的其他人的工作。

(I do not know however if you will run into other issues with .2.12 - just know my app is routing and I'm not getting a "'..Controller' function, is undefined" error any longer) (但是,我不知道您是否会在.2.12中遇到其他问题-只知道我的应用程序正在路由并且我不再遇到“'..Controller'函数,未定义”错误)

I have an open issue on github: https://github.com/marcoslin/angularAMD/issues/154 我在github上有一个公开的问题: https : //github.com/marcoslin/angularAMD/issues/154

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

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