简体   繁体   English

使用AngularJS / $ controllerProvier和RequireJS动态加载控制器和视图时遇到麻烦

[英]Trouble with dynamically loading controllers and views with AngularJS/$controllerProvier and RequireJS

I cam across this blog posting from Dan Wahlin about dynamically loading controllers and views. 我浏览了Dan Wahlin的这篇博客文章 ,内容涉及动态加载控制器和视图。 I downloaded the source from github and tried to reproduce the project on a smaller scale to understand how it all worked. 我从github下载了源代码,并试图以较小的比例重现该项目,以了解其工作原理。 I can get the project to load with the views but where I am stuck is on figuring out why the controller does not seem to bind to the view. 我可以使项目加载视图,但我遇到的问题是弄清楚为什么控制器似乎未绑定到视图。 Stepping through the code I can see the controller being initialized and injected into the app: 逐步执行代码,我可以看到控制器已初始化并注入到应用程序中:

here you can see the app initialize and routes are established 在这里您可以看到应用程序初始化并建立了路由

'use strict';

define(['services/routeResolver'], function () {

    var app = angular.module('myApp', ['ngRoute', 'ngAnimate', 'ui.bootstrap', 'breeze.angular', 'routeResolverServices']);

    app.config(['$routeProvider', 'routeResolverProvider', '$controllerProvider',
                '$compileProvider', '$filterProvider', '$provide', '$httpProvider',

     function ($routeProvider, routeResolverProvider, $controllerProvider,
               $compileProvider, $filterProvider, $provide, $httpProvider) {

         app.register = {
             controller: $controllerProvider.register,
             directive: $compileProvider.directive,
             filter: $filterProvider.register,
             factory: $provide.factory,
             service: $provide.service
         };

         //From Dan Whalin project comments: route.resolve() now accepts the convention to use (name of controller & view) as well as the 
         //path where the controller or view lives in the controllers or views folder if it's in a sub folder. 
         // first param is the name of the controller, second param is the directory it and the view exist in, third param is the alias (controller as) optional third param is true false for security 

         var route = routeResolverProvider.route;
         $routeProvider
         .when('/', route.resolve('main', '', 'vm'))
         .otherwise({ redirectTo: '/' });
     }
    ]);

    ////support for lodash
    //   app.factory('_', ['$window', function ($window) {
    //       return $window._;
    //   }]);

    // breeze factory manager
       app.factory('entityManagerFactory', ['breeze', emFactory]);

       function emFactory(breeze) {
           // Convert properties between server-side PascalCase and client-side camelCase
           breeze.NamingConvention.camelCase.setAsDefault();

           // Identify the endpoint for the remote data service
           var serviceRoot = window.location.protocol + '//' + window.location.host + '/';
           var serviceName = serviceRoot + 'breeze/breeze'; // breeze Web API controller

           // the "factory" services exposes two members
           var factory = {
               newManager: function () { return new breeze.EntityManager(serviceName); },
               serviceName: serviceName
           };
           return factory;
       };

       app.service("httpDataLoader", ["$http", function ($http) {
           this.load = function () {
               return $http();
           }
       }]);

    //global filter to allow html to render in the UI and bypass SCE (secure content expression)
    //usage: ng-html-bind="properyExpresson | html"
       app.filter('html', ['$sce', function ($sce) {
           return function (text) {
               return $sce.trustAsHtml(text);
           }
       }
       ]);

    app.run(['breeze', function (breeze) { }]);//currently doing nothing
    return app;
});

UPDATE 更新

A question was asked about the route resolver and how it was supposed to work: From Dan Wahlin Bolg: 有人问了有关路径解析器及其应如何工作的问题:来自Dan Wahlin Bolg:

The routeResolver.js script creates an AngularJS provider. routeResolver.js脚本创建一个AngularJS提供程序。 It's loaded by RequireJS and used in app.js within the config() function to define routes and resolve them dynamically at runtime. 它由RequireJS加载,并在config()函数中的app.js中使用,以定义路由并在运行时动态解析它们。

AngularJS already comes with built-in support for loading views dynamically and with a little more work controllers can be loaded dynamically as well. AngularJS已经内置了对动态加载视图的支持,并且还可以动态加载更多的工作控制器。 Loading controller scripts can be done by assigning the resolve property mentioned earlier to a function that handles loading the controller. 可以通过将前面提到的resolve属性分配给处理加载控制器的函数来完成加载控制器脚本。 What's unique about routeResolver is that it doesn't accept hard-coded paths to the target view or controller. routeResolver的独特之处在于它不接受到目标视图或控制器的硬编码路径。 Instead, you define a base name such as “main” and the resolver will generate the path to the appropriate view and controller based on a standard convention. 取而代之的是,您定义基本名称(例如“ main”),解析器将基于标准约定生成指向相应视图和控制器的路径。

within main.js I define the files to load with require 在main.js中,我定义了需要加载的文件

requirejs.config({
    baseUrl: 'app',
    urlArgs: 'v=1.0',
});

require([
    'app',
    'services/routeResolver',
    'services/config',
    'services/dataService'
],
function () {
    angular.bootstrap(document, ['myApp']);
});

and within my mainController I setup a basic controller 在我的mainController中,我设置了一个基本控制器

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

    var injectParams = ['$window', 'dataService'];

    var mainController = function($window, dataService){

        var vm = this;
        vm.message = 'we are wired up';

        vm.connect = function () {
            alert('hello')
        };
    };

    mainController.$inject = injectParams;
    app.register.controller('mainController', mainController);
});

index.html is setup as index.html设置为

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <base href="/">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="Content/bootswatch-slate.css" rel="stylesheet" />
    <title></title>
</head>
<body ng-cloak>
    <div ng-view></div>


    <script src="Scripts/angular.min.js"></script>
    <script src="Scripts/angular-route.min.js"></script>
    <script src="Scripts/angular-animate.min.js"></script>
    <script src="Scripts/angular-sanitize.min.js"></script>
    <script src="Scripts/angular-ui/ui-bootstrap.min.js"></script>
    <script src="Scripts/breeze.min.js"></script>
    <script src="Scripts/breeze.bridge.angular.js"></script>

    <script src="Scripts/require.js" data-main="Scripts/main"></script>
</body>
</html>

and the main view is pretty basic 而且主视图很基本

<div>
    <p>static text</p>
    <p>{{vm.message}}</p>
    <button type="button" ng-click="vm.connect()">click</button>
</div>

What I am seeing in the project is the page/view load fine and within the dev tools I can see the controller as well as all scripts initialize. 我在项目中看到的是页面/视图加载良好,在开发工具中,我可以看到控制器以及所有脚本初始化。 However the scoped items within the controller vm.message or the function call vm.connect are not bound or recognized from the view. 但是,从视图中未绑定或识别控制器vm.message或函数调用vm.connect中的作用域项目。 Dev Tools show no error in the console and the view with static content renders. 开发工具不会在控制台中显示任何错误,并且具有静态内容的视图会呈现。 I think I may be getting fooled with the scope of the controllers is either getting duplicated or I am somehow not injecting it correctly. 我想我可能对控制器的范围迷惑了,要么是重复的,要么是我不正确地注入了它。 I tried to use the Angular extension to observe the scope and watches but it would error out. 我试图使用Angular扩展来观察范围和手表,但是会出错。 I got the same error when I ran the source project from gitHub, but with the angular extension turned off the source project runs fine. 当我从gitHub运行源项目时,我遇到了相同的错误,但是在关闭了角度扩展的情况下,源项目运行正常。

I tried to setup a plnkr but due to the configuration/routing of the project it wouldn't run so here is a link to the full solution from VS. 我尝试设置plnkr,但是由于项目的配置/路由无法运行,因此这里是 VS 完整解决方案的链接 The code is on a GoogleDrive share if I need to move it to another repository please let me know. 如果我需要将代码移至另一个存储库,则该代码位于GoogleDrive共享上。 I would appreciate any code review and suggestion on what I have missed or overlooked. 我将对我遗漏或忽略的内容进行任何代码审查和建议,我将不胜感激。 In comparing my code to what is in Dan's solution it appears to be the same. 在将我的代码与Dan解决方案中的代码进行比较时,它似乎是相同的。

I'd appreciate any suggestions or ideas 我将不胜感激任何建议或想法

thanks 谢谢

There were differents between the code in blog post and github. 博客文章和github中的代码之间存在差异。

As routeResolverProvider.route.resolve() on the blog post only support 3 parameters 由于博客文章上的routeResolverProvider.route.resolve()仅支持3个参数

function (baseName, path, secure) {...}

And on github, it is instead support 4 parameters 在github上,它支持4个参数

function (baseName, path, controllerAs, secure) {...}

So the only possiblily for controllerAs mis-registered with $routeProvider is the code on blog post was used. 因此,唯一可能在controllerAs$routeProvider错误注册的是使用博客文章上的代码。 And routeResolverProvider.route.resolve() is not supporting controllerAs configuration. 并且routeResolverProvider.route.resolve()不支持controllerAs配置。

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

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