مسیریابی AngularJS با تایپاسکریپت


من از قالب زیر برای پیکربندی یک برنامه وب AngularJS/Typescript استفاده میکنم و خطای زیر را دریافت میکنم.

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.

من این بحث را بررسی کردهام و اطمینان حاصل کردهام که واقعاً ارجاعی به angular-route.js دارم

app.ts - نسخه آسانتر برای مشاهده + 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: نمیتوان $routeProvider را تزریق کرد

پاسخ شماره ۱

شما نیاز دارید چند تغییر در آن قالب ایجاد کنید تا کار کند.

منبع کامل در اینجا

ابتدا اطمینان حاصل کنید که مراجع صحیح را دارید. شامل ارجاع به 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: '/'
            });
    }
]);

تایپاسکریپت بعدی ماژولهای خالی را قبول نخواهد کرد. بنابراین داشتن 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-route.js بعد از angular.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>