Multiple modules in Angular 2

RyanGled picture RyanGled · Oct 3, 2016 · Viewed 7.6k times · Source

I have an Angular 2 app (RC7) which started as a single component but is quickly becoming used throughout the project in various different (and sometimes completely unrelated) ways.

As a result of this, a single NgModule bootstrapping all the components seems like a terrible idea with a huge amount of bloat. I am struggling to find a way to have multiple modules (Module A would contain Component A, Module B would have Component B, etc) and still allow the bootstrapping of multiple A2 applications on a single page.

In practice, what I am trying to achieve is this:

Page 1 bootstraps Module A - this works.

Page 2 bootstraps Module B - this works.

Page 3 bootstraps Module A & Module B - this doesn't work.

index.html

<script src="/angular2/node_modules/zone.js/dist/zone.js"></script>
<script src="/angular2/node_modules/reflect-metadata/Reflect.js"></script>
<script src="/angular2/node_modules/systemjs/dist/system.src.js"></script>
<script src="/angular2/systemjs.config.js"></script>


<script type="text/javascript">
    System.import('appOne').catch(function(err){ console.error(err); });
    System.import('appTwo').catch(function(err){ console.error(err); });
</script>

systemjs.config.js

(function (global) {
    System.config({
        paths: {
            'npm:': '/angular2/node_modules/'
        },
        map: {
            appOne: '/angular2/',
            appTwo: '/angular2/',
        },
        packages: {
            appOne: {
                main: './appOne.main.js',
                defaultExtension: 'js'
            },
            appTwo: {
                main: './appTwo.main.js',
                defaultExtension: 'js'
            },
        }
    });
})(this);

AppOne and AppTwo's modules simply bootstrap the relevant component (componentOne & componentTwo). However, both will not render on the same page at the same time. I have no errors in the console, but whichever package is listed last within the systemjs.config.js file is the only one to load.

Can anyone see why it might not be working? Or perhaps recommend another way to structure my modules. I'd rather not have one parent module with all components, services, etc listed - this seems to defeat the point of Angular 2's nested Component trees, and will eventually affect page-load times exponentially.

Thanks in advance.

Answer

jcmordan picture jcmordan · Nov 1, 2016

You can boostrap an array of components from AppModule, something like this:

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import {AppComponent} from "./app.component";
import {MainSidebarComponent} from "./menus/main-sidebar.component";
import {FormsModule} from "@angular/forms";
import {appRouting} from "./app.routes";
import {DashBoardComponent} from "./dashboard/dashboard.component";
import {HomeComponent} from "./home/home.component";
import {LoginComponent} from "./login/login.component";
import {UsersModule} from "./users/users.module";
import {TopBarComponent} from "./menus/top-bar.component";

@NgModule({
    imports:      [
        BrowserModule,
        FormsModule,
        appRouting,

        UsersModule
    ],
    declarations: [
        AppComponent,
        MainSidebarComponent,
        TopBarComponent,
        DashBoardComponent,
        HomeComponent,
        LoginComponent
    ],
    bootstrap:    [ AppComponent, MainSidebarComponent, TopBarComponent ]
})
export class AppModule { }

Then in your index.html

<!doctype html>
<head>
    <base href="/">
    <meta charset="UTF-8">

    <!-- 1. Load libraries -->
    <!-- Polyfill(s) for older browsers -->
    <script src="node_modules/core-js/client/shim.min.js"></script>
    <script src="node_modules/zone.js/dist/zone.js"></script>
    <script src="node_modules/reflect-metadata/Reflect.js"></script>
    <script src="node_modules/systemjs/dist/system.src.js"></script>
    <!-- 2. Configure SystemJS -->
    <script src="systemjs.config.js"></script>
    <script>
        System.import('app').catch(function (err) {
            console.error(err);
        });
    </script>
</head>
<body class=" sidebar_main_open sidebar_main_swipe">

<header id="header_main">
 <top-bar></top-bar>
</header><


<aside id="sidebar_main">
    <main-sidebar></main-sidebar>
</aside>


<div id="page_content">
    <div id="page_content_inner">
        <my-app>Loading....</my-app>
    </div>
</div>
</body>
</html>