Tips for bundling TypeScript Angular with internal modules using SystemJS

We have been exploring the idea of transitioning some of our angular projects to typescript, but we are encountering difficulties with internal modules/namespaces.

For reference, we have shared a working example on github: https://github.com/hikirsch/TypeScriptSystemJSAngularSampleApp

Here are the steps to follow:

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

This is the essence 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;
    }
}

Although everything works fine in the current setup mentioned above, we would prefer to encapsulate everything within a namespace like so:

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

and then use it in this manner:

After compiling correctly with the gulp bundle task, an error occurs 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)

Answer №1

According to the typescript documentation, it is unnecessary to use internal modules when compiling to commonjs. As mentioned:

One advantage of external modules in TypeScript is that different external modules will not introduce names into the same scope. Since the consumer of an external module determines what name to give it, there is no need to proactively wrap up exported symbols in a namespace.

I have discovered that the most effective way to utilize TypeScript with a commonjs loader (such as browserify) is to follow this pattern:

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

    constructor() {

    }

    public name:string;
    public text:string;

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

export = ExampleTwoCtrl

and then use it like this:

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

Having said that, I recently watched a presentation by John Papa at AngularU where they showcased some code bundled using systemjs written in TypeScript without any imports, just internal ts modules. I reached out on Twitter inquiring about the sample code location but have yet to receive a response.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Ways to control the number of function invocations in an AngularJS controller

I am facing a challenge where data is being fetched from multiple controllers, causing functions to hit the server more than fifty times until they receive a response. I am unsure how to handle this situation effectively and would appreciate some guidance. ...

Showing JSON data as a list in Angular 7

I'm encountering a problem trying to display JSON data in a list format. It seems like something is missing because the data isn't showing up. Below is the code I've been using: Service: getData() { this.http.post('http://localho ...

Methods for setting a global instance within a local function

Hello, I'm fairly new to using TypeScript and Angular2. Let me quickly explain what I'm trying to accomplish with my method. I have some hard-coded XML data that I need to parse into JSON format. Once parsed, each JSON object needs to be assigned ...

Guidelines for activating TypeScript intellisense in VSCode for a JavaScript codebase while implementing module augmentation for a third-party library

When working with a standard create-react-app setup, I often find myself needing to import a third-party component as and when required: import { Button } from '@mui/material' // […] <Button variant="|"></Button> This li ...

What are the steps to enable full functionality of the strict option in TypeScript?

Despite enforcing strict options, TypeScript is not flagging the absence of defined types for port, req, and res in this code snippet. I am using Vscode and wondering how to fully enforce type checking. import express from 'express'; const app ...

Checking for queryParam changes in Angular before ngOnDestroy is invoked

I am looking to conditionally run some code in the ngOnDestroy function depending on changes in the current route. Specifically, when the route changes from /foo to /login?logout=true, and this change is initiated outside of the Foo component. In the ngO ...

Display the information within an array

Using React with TypeScript to set an image file to useState Initially, I set it directly like this: <div> {img[0]} </div> When viewing the webpage: <div> 'string =>'<img src={require("../../asset/images/img_pictu ...

Using Angular 4 constructor value in a condition with *ngIf

Within this TypeScript snippet, there is a variable called moreinfo that is initially set to 1. In the constructor, however, the value of moreinfo is changed to 2. Subsequently, based on whether the value is 1 or 2, different div elements are displayed usi ...

How the web api response might contain a null value

I currently have a Web Api controller set up to access data from the server: public class ServicesController : ApiController { [AcceptVerbs("POST")] public IList<TreeMenuItem> LoadMetadata() { List<TreeMenuItem> itemsMenu = ...

TS2304: The build process is unable to locate the name 'iterable' within @types

As an experienced dog attempting to master new tricks like npm and TypeScript, I find myself faced with a challenge in my Visual Studio 2017 project. Despite setting it to "Latest" TypeScript 2.5 and adding @types/jquery (3.2.12), the project keeps throwin ...

Retrieving information from a JSON object in Angular using a specific key

After receiving JSON data from the server, I currently have a variable public checkId: any = 54 How can I extract the data corresponding to ID = 54 from the provided JSON below? I am specifically looking to extract the values associated with KEY 54 " ...

What is the trick to creating fluid, animated charts using zingchart?

I've been attempting to showcase charts using AngularJS tags, and although everything seems to be functioning correctly, the animation feature isn't working as expected. Does anyone have any suggestions on how to enable continuous animation? Any ...

The Intersection of Material-UI, TypeScript, and Powerful Autocomplete Features

In my TypeScript project, I'm attempting to develop a Material-UI AutoComplete component that retrieves the input value based on an object's property name -> obj[key] However, when using the prop getOptionLabel, I encountered the following er ...

Angular: No routes found that match the URL segment

I encountered an issue with my routes module where I am receiving the error message Cannot match any routes. URL Segment: 'edit-fighter' when attempting to navigate using the <a> link. The only route that seems to work is the champions-list ...

Nativescript encountered an issue while attempting to generate the application. The module failed to load: app/main.js

I'm currently experimenting with the sample-Groceries application, and after installing NativeScript and angular 2 on two different machines, I encountered the same error message when trying to execute: tns run android --emulator While IOS operations ...

Guide on executing MySQL queries in AngularJS with the help of the Laravel 4 framework

I am having issues executing MySql Queries in the Laravel framework using AngularJS. I am currently unable to successfully delete a database record through the button functionality. The existing code is able to insert data into the database, retrieve data ...

Utilizing ng-options for dropdown selection with the "as" syntax in AngularJS

When I use ng-options to define options in a select element, everything works fine with just the controller name within the ng-controller directive. However, adding "as options" to the ng-controller causes it to stop working (no options are displayed). Ex ...

Using Typescript to incorporate Next.js on Firebase Functions

I'm currently working on deploying a Next.js application to Firebase Functions. import next from 'next' import {https} from 'firebase-functions' const server = next({ dev: process.env.NODE_ENV !== 'production', conf: ...

Utilizing Angular 10 to Transform a JSON Data into a Custom String for HTML Rendering

I have received a JSON response from my backend built using Spring Boot. The "category" field in the response can either be 1 or 2, where 1 represents Notifications and 2 represents FAQs. { "pageNumber": 0, "size": 5, "totalPages&q ...

Setting up Material-UI for React in conjunction with Typescript: A step-by-step guide

I've encountered issues while trying to integrate Material UI into my React project that's written in Typescript. Following the tutorial, I began by adding the react-tab-event-plugin. import injectTapEventPlugin from 'react-tap-event-plugi ...