5

We are considering moving some of our angular projects over to typescript and having some trouble with internal module/namespaces.

We posted this working example on github: https://github.com/hikirsch/TypeScriptSystemJSAngularSampleApp

steps:

npm install jspm -g
npm install
cd src/
jspm install
jspm install --dev
cd ..
gulp bundle
cd src/
python -m SimpleHTTPServer

This is the gist of the application: index.ts

/// <reference path="../typings/tsd.d.ts" />
/// <reference path="../typings/typescriptApp.d.ts" />

import * as angular from 'angular';

import {ExampleCtrl} from './controllers/ExampleCtrl';
import {ExampleTwoCtrl} from './controllers/ExampleTwoCtrl';

export var app = angular.module("myApp", []);

app.controller("ExampleCtrl", ExampleCtrl);
app.controller("ExampleTwoCtrl", ExampleTwoCtrl);

ExampleCtrl.ts

/// <reference path="../../typings/tsd.d.ts" />
/// <reference path="../../typings/typescriptApp.d.ts" />


export class ExampleCtrl {
    public static $inject:Array<string> = [];

    constructor() {

    }

    public name:string;
    public hello_world:string;

    public say_hello() {
        console.log('greeting');

        this.hello_world = "Hello, " + this.name + "!";
    }
}

ExampleTwoCtrl.ts

/// <reference path="../../typings/tsd.d.ts" />
/// <reference path="../../typings/typescriptApp.d.ts" />

export class ExampleTwoCtrl {
    public static $inject:Array<string> = [];

    constructor() {

    }

    public name:string;
    public text:string;

    public second() {
        this.text = "ExampleTwoCtrl: " +  this.name;
    }
}

As stated, this works all well and good. But we'd rather have everything under a namespace like this:

module myApp.controllers {
    export class ExampleController {
        ...
    }
}
//do we need to export something here?

and then use it like this:

This will compile correctly running the gulp bundle task but give an error in the browser /// ///

import * as angular from 'angular';

import ExampleCtrl = myApp.controllers.ExampleCtrl;
import ExampleTwoCtrl = myApp.controllers.ExampleTwoCtrl;

export var app = angular.module("myApp", []);

app.controller("ExampleCtrl", ExampleCtrl);
app.controller("ExampleTwoCtrl", ExampleTwoCtrl);

browser error:

Uncaught ReferenceError: myApp is not defined(anonymous function) @ build.js:5u @ build.js:1i @ build.js:1c @ build.js:1(anonymous function) @ build.js:1(anonymous function) @ build.js:1
build.js:1 Uncaught Error: [$injector:modulerr] Failed to instantiate module myApp due to:
Error: [$injector:nomod] Module 'myApp' 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.
http://errors.angularjs.org/1.3.15/$injector/nomod?p0=myApp
    at http://localhost:8000/build/build.js:1:4007
    at http://localhost:8000/build/build.js:1:12353
    at e (http://localhost:8000/build/build.js:1:11925)
    at t.register.e (http://localhost:8000/build/build.js:1:12237)
    at http://localhost:8000/build/build.js:1:20741
    at o (http://localhost:8000/build/build.js:1:4392)
    at p (http://localhost:8000/build/build.js:1:20519)
    at Bt (http://localhost:8000/build/build.js:1:22209)
    at t.register.s (http://localhost:8000/build/build.js:1:10038)
    at Q (http://localhost:8000/build/build.js:1:10348)
http://errors.angularjs.org/1.3.15/$injector/modulerr?p0=myApp&p1=Error%3A%…0%20at%20Q%20(http%3A%2F%2Flocalhost%3A8000%2Fbuild%2Fbuild.js%3A1%3A10348)

1 Answer 1

2

According to typescript documentation you do not need to use internal modules when compiling to commonjs. As stated:

A key feature of external modules in TypeScript is that two different external modules will never contribute names to the same scope. Because the consumer of an external module decides what name to assign it, there's no need to proactively wrap up the exported symbols in a namespace.

I have found the best way to use typescript with a commonjs loader (I am using browserify) is to do something like:

class ExampleTwoCtrl {
    public static $inject:Array<string> = [];

    constructor() {

    }

    public name:string;
    public text:string;

    public second() {
        this.text = "ExampleTwoCtrl: " +  this.name;
    }
}

export = ExampleTwoCtrl

and the use it like:

import MyController = require('./ExampleTwoCtrl');
var a = new MyController();

That being said, I watched the recording from John Papa's talk at AngularU where they demonstrated some code bundled using systemjs written in typescript without any imports, just internal ts modules. I asked on twitter where I could find the sample code, but haven't got a response yet.

Sign up to request clarification or add additional context in comments.

5 Comments

The sample code there were using is linked to here on slide 18 docs.google.com/presentation/d/…
The approach they use essentially just dumps a script tag for every JS in the project onto the html page regardless if its being used or not. We were looking for an approach where we could tell it which file starts the app and have it build the file appropriately. What we have without using modules seems to accomplish it. Just trying to figure out how we can make that work with modules (essentially just want everything namespaced)
I thought so too, but it's not. If you check index.html (github.com/johnpapa/hottowel-angular-typescript/blob/master/src/…) it does not use systemjs at all. The code they where showing was different, as there was a systemjs and some other files and a single script that loads main.js (if I remember correctly, min 50 of the video)
also @1:05 there is an example of System.import('app/app') in index.html and then the app.ts containing the configuraion, import and bootstrap of all the other stuff.
I actually spoke with John papa on this matter, I don't think he would go the route with SystemJS. I think he prefer to bundle everything at once and load it. I think he believe in general situation, your javascript files excludes vendor files shouldn't be that big.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.