Reputation: 128
Am using the following template to configure a AngularJS/Typescript web app and receiving the following error.
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.
I have checked this thread and ensured that I do indeed have a reference to 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);
}
}
Am a bit of a TS/Angular newbie so any help would be greatly appreciated.
Thanks
Potential Duplicate: AngularJS + TypeScript: cannot inject $routeProvider
Upvotes: 3
Views: 17540
Reputation: 572
I found my sollution here a link:
It happens when I tried to include a module dependency that did not exist. This happens due to a number of reasons such as removing a script for index.html for a module but leaving in the module dependency or even misspelling a module dependency. (Turns out my issue was the former.) So this was easy to fix once you knew that.
Upvotes: -2
Reputation: 21521
You need to make a few changes to that template to get it to work.
First ensure you have the correct references. Including a reference to 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, []));
To use the $routeProvider
you must have included the ngRoute
module in your modules, but because we don't want to register it with angular, because it already exists there, we need to push the module afterwards like this:
// *** Push ngRoute or $routeProvider won't work ***
modules.push("ngRoute");
angular.module('app', modules);
Then you need to fix the type of $routeProvider
from ng.IRouteProvider
to ng.route.IRouteProvider
as that definition is wrong.
// 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 won't accept empty modules. So having export module controllers {}
etc is pointless, because TSC won't include them, and they will be undefined giving errors. Unless you were to define at least one controller, directive, filter and service in your app. But this is solved by simply including 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);
}
}
That should now work and you can register your controllers, filters, services and directives. Such as:
module app.controllers
{
export class testCtrl implements IController
{
constructor()
{
console.log("Test Controller");
}
}
}
app.registerController('testCtrl');
When referencing a controller, or service to use the full name. i.e:
<div ng-controller="app.controllers.testCtrl"></div>
Remember in your html to reference angular-route.js
after angular.js
. i.e:
<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>
Upvotes: 14