AngularJS Typescript 路由

Posted

技术标签:

【中文标题】AngularJS Typescript 路由【英文标题】:AngularJS Typescript Routing 【发布时间】:2014-03-14 20:18:58 【问题描述】:

我正在使用 following template 配置 AngularJS/Typescript Web 应用程序并收到以下错误。

The following error is appearing when I run the application:
0x800a139e - javascript runtime error: [$injector:modulerr] Failed to instantiate module app due to:

Error: [$injector:nomod] Module 'app' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.

我检查了this thread 并确保我确实引用了 angular-route.js

app.ts - Easier version to view + index.html

  /// <reference path="./typings/angularjs/angular.d.ts" />
'use strict';

// Create and register modules
var modules = ['app.controllers','app.directives', 'app.filters', 'app.services'];
modules.forEach((module) => angular.module(module, []));
angular.module('app', modules);

// Url routing
angular.module('app').config(['$routeProvider',
    function routes($routeProvider: ng.IRouteProvider) 
        $routeProvider
            .when('/', 
                templateUrl: 'views/MyView.html',
                controller: 'app.controllers.MyController'
            )
            .otherwise(
                redirectTo: '/'
            );
    
]);

module app 
    export module controllers 
    export module directives 
    export module filters 
    export module services 

    export interface IController 
    export interface IDirective 
        restrict: string;
        link($scope: ng.IScope, element: JQuery, attrs: ng.IAttributes): any;
    
    export interface IFilter 
        filter (input: any, ...args: any[]): any;
    
    export interface IService 

    /**
     * Register new controller.
     *
     * @param className
     * @param services
     */
    export function registerController (className: string, services = []) 
        var controller = 'app.controllers.' + className;
        services.push(app.controllers[className]);
        angular.module('app.controllers').controller(controller, services);
    

    /**
     * Register new filter.
     *
     * @param className
     * @param services
     */
    export function registerFilter (className: string, services = []) 
        var filter = className.toLowerCase();
        services.push(() => (new app.filters[className]()).filter);
        angular.module('app.filters').filter(filter, services);
    

    /**
     * Register new directive.
     *
     * @param className
     * @param services
     */
    export function registerDirective (className: string, services = []) 
        var directive = className[0].toLowerCase() + className.slice(1);
        services.push(() => new app.directives[className]());
        angular.module('app.directives').directive(directive, services);
    

    /**
     * Register new service.
     *
     * @param className
     * @param services
     */
    export function registerService (className: string, services = []) 
        var service = className[0].toLowerCase() + className.slice(1);
        services.push(() => new app.services[className]());
        angular.module('app.services').factory(service, services);
    

我是一个 TS/Angular 新手,因此我们将不胜感激。

谢谢

潜在重复:AngularJS + TypeScript: cannot inject $routeProvider

【问题讨论】:

您使用的是哪个版本的 Typescript?该模板很旧,并且在 0.9.1.10.9.5 分支上都抛出了错误。 我相信我在 0.9.21 【参考方案1】:

您需要对该模板进行一些更改才能使其正常工作。

Full source here

首先确保您有正确的参考。包括对angular-route.d.ts的引用

/// <reference path="./typings/angularjs/angular.d.ts" />
/// <reference path="./typings/angularjs/angular-route.d.ts" />

'use strict';

// Create and register modules
var modules = ['app.controllers','app.directives', 'app.filters', 'app.services'];
modules.forEach((module) => angular.module(module, []));

要使用$routeProvider,你必须在你的模块中包含ngRoute模块,但是因为我们不想用angular注册它,因为它已经存在,我们需要像这样推送模块:

// *** Push ngRoute or $routeProvider won't work ***
modules.push("ngRoute");

angular.module('app', modules);

那么你需要将$routeProvider的类型从ng.IRouteProvider改成ng.route.IRouteProvider,因为那个定义是错误的。

// Url routing
angular.module('app').config(['$routeProvider',
    function routes($routeProvider: ng.route.IRouteProvider)  // *** $routeProvider is typed with ng.route.IRouteProvider ***
        $routeProvider
            .when('/', 
                templateUrl: 'views/MyView.html',
                controller: 'app.controllers.MyController'
            )
            .otherwise(
                redirectTo: '/'
            );
    
]);

Next TypeScript 不接受空模块。所以拥有export module controllers 等是没有意义的,因为 TSC 不会包含它们,并且它们将是未定义的给出错误。除非您要在应用程序中定义至少一个控制器、指令、过滤器和服务。但这可以通过简单地包含 null;

来解决
module app 
    export module controllers  null; 
    export module directives  null; 
    export module filters  null; 
    export module services  null; 

    export interface IController 
    export interface IDirective 
        restrict: string;
        link($scope: ng.IScope, element: JQuery, attrs: ng.IAttributes): any;
    
    export interface IFilter 
        filter (input: any, ...args: any[]): any;
    
    export interface IService 

    /**
     * Register new controller.
     *
     * @param className
     * @param services
     */
    export function registerController (className: string, services = []) 
        var controller = 'app.controllers.' + className;
        services.push(app.controllers[className]);
        angular.module('app.controllers').controller(controller, services);
    

    /**
     * Register new filter.
     *
     * @param className
     * @param services
     */
    export function registerFilter (className: string, services = []) 
        var filter = className.toLowerCase();
        services.push(() => (new app.filters[className]()).filter);
        angular.module('app.filters').filter(filter, services);
    

    /**
     * Register new directive.
     *
     * @param className
     * @param services
     */
    export function registerDirective (className: string, services = []) 
        var directive = className[0].toLowerCase() + className.slice(1);
        services.push(() => new app.directives[className]());
        angular.module('app.directives').directive(directive, services);
    

    /**
     * Register new service.
     *
     * @param className
     * @param services
     */
    export function registerService (className: string, services = []) 
        var service = className[0].toLowerCase() + className.slice(1);
        services.push(() => new app.services[className]());
        angular.module('app.services').factory(service, services);
    

现在应该可以了,您可以注册控制器、过滤器、服务和指令。如:

module app.controllers

    export class testCtrl implements IController
    
        constructor()
        
            console.log("Test Controller");
        
    


app.registerController('testCtrl');

当引用一个控制器,或服务时使用全名。即:

<div ng-controller="app.controllers.testCtrl"></div>

请记住在您的 html 中在 angular.js 之后引用 angular-route.js。即:

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular-route.js"></script>

【讨论】:

斯科特你的回答成功地解决了我的主要问题,所以再次非常感谢,但是我现在收到一个次要错误,说它无法加载模块 ngLocale。 (oi62.tinypic.com/ojkon.jpg) 在哪里(以及如何)在 app.ts 中加载这个模块?我在这里查看了文档:docs.angularjs.org/error/$injector/nomod,但我无法完全理解它。 @freschx 您可以在当前modules.push("ngRoute"); 行之后使用modules.push("moduleName"); 向模板添加更多模块。所以在这种情况下modules.push("ngLocale");。希望有帮助:) @Scott 有没有办法将module app.controllers 放入不同的文件中?我想将我的控制器打字稿文件拆分到不同的目录中。我试图将它拆分出来,但它没有注册任何控制器。【参考方案2】:

我在这里找到了我的解决方案a link:

当我试图包含一个不存在的模块依赖项时会发生这种情况。发生这种情况的原因有很多,例如删除模块的 index.html 脚本但留下模块依赖关系,甚至拼写错误的模块依赖关系。 (原来我的问题是前者。)所以一旦你知道这一点就很容易解决。

【讨论】:

以上是关于AngularJS Typescript 路由的主要内容,如果未能解决你的问题,请参考以下文章

TypeScript 中的 Angular 材质示例:芯片

迈向angularjs2系列:typescript指南

AngularJs + typescript 指令依赖注入

如何使用 TypeScript 解决 AngularJS 指令

带有 ControllerAs 和 TypeScript 类的 AngularJs 指令

Angularjs+Typescript 指令实现 $compile