Join the social network of Tech Nerds, increase skill rank, get work, manage projects...
 
  • Manual Bootstrapping of an Application - Angular 5

    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 1
    • 0
    • 1.33k
    Comment on it

    Whenever a new angular project is created, automatically a root module "AppModule" in file app.module.ts and a root component "AppComponent" in file app.component.ts is provided. Bootstrapping in angular is performed in two stages. 

     

     

    First, main application module originally "AppModule" is bootstrapped via bootstrapModule method of the platform "platformBrowserDynamic()"is used. 

     

    main.ts file

    import { enableProdMode } from '@angular/core';
    import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
    import { AppModule } from './app/app.module';
    import { environment } from './environments/environment';
    
    if (environment.production) {
     enableProdMode();
    }
    
    platformBrowserDynamic().bootstrapModule(AppModule)
     .catch(err => console.log(err));


      
    Second bootstrapping root component in this case "AppComponent" in main application module.

     

    app.module.ts - Contains Root Module

    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import { AppComponent } from './app.component';
    
    @NgModule({
     declarations: [
      AppComponent,
     ],
     imports: [
      BrowserModule
     ],
     bootstrap:[AppComponent],
     providers: []
    })
    export class AppModule {}

    The component which bootstrap the application is referred by property - "bootstrap: [AppComponent]". When the application runs, angular finds the element in file "index.html" that is the selector of a bootstrapped component in the DOM and initializes the component. This process signifies that we are aware of the component we want to bootstrap the application with.  Initially, the application is bootstrapped with root component "AppComponent".

     

    app.component.ts -file containing root or parent component

    import { Component } from '@angular/core';
    
    @Component({
     selector: 'app-root',
     templateUrl: './app.component.html',
     styleUrls: ['./app.component.css']
    })
    export class AppComponent {
     title = 'app';
    }

     

    index.html

    <!doctype html>
    <html lang="en">
    <head>
     <meta charset="utf-8">
     <title>AngularManualBootstrap</title>
     <base href="/">
    
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <link rel="icon" type="image/x-icon" href="favicon.ico">
    </head>
    <body>
     <app-root></app-root>   //selector of bootstrapped component
    </body>
    </html>

     

    Sometimes a requirement may arise when bootstrapping the application with a particular component is defined by the server during runtime. This is known as manual bootstrapping.

     

    Consider following example for manual bootstrapping:-
    Create two new components Admin Component and User Component. The decision which component is to be used for bootstrapping the application is made at runtime.

     

    admin.component.ts  -file containing AdminComponent

    import { Component, OnInit } from '@angular/core';
    
    @Component({
     selector: 'app-admin',
     template: '<h3>This component is used for application admin.</h3>',
    })
    export class AdminComponent implements OnInit {
    
     constructor() { }
    
     ngOnInit() {
     }
    
    }

     

    user.component.ts -file containing UserComponent

    import { Component, OnInit } from '@angular/core';
    
    @Component({
     selector: 'app-user',
     template:'<h3>This component is used for application user.</h3>'
    })
    export class UserComponent implements OnInit {
    
     constructor() { }
    
     ngOnInit() {
     }
    }

     

    The app.module.ts file is changed to

    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import { AppComponent } from './app.component';
    import { AdminComponent } from './admin/admin.component';
    import { UserComponent } from './user/user.component';
    
    @NgModule({
     declarations: [
      AppComponent,
      AdminComponent,
      UserComponent
     ],
     imports: [
      BrowserModule
     ],
     bootstrap:[],
     entryComponents:[
      AdminComponent,UserComponent
     ],
     providers: []
    })
    export class AppModule {}

     

    We can observe that bootstrap property is empty as which component the application will be bootstrapped with will be decided at runtime. Instead, two newly created components are registered within entryComponents property so as to create factories for these components. Previously root component "AppComponent" was not added to entryComponents because angular automatically adds components specified in the bootstrap property to entry components.

     

    The index.html is chaged to

    <!doctype html>
    <html lang="en">
    <head>
     <meta charset="utf-8">
     <title>AngularManualBootstrap</title>
     <base href="/">
    
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <link rel="icon" type="image/x-icon" href="favicon.ico">
    </head>
    <body>
     <h1 id="componentstatus">
      Loading Component content here ... //No selector as it is decided at run time
     </h1>
    </body>
    </html> 


     
    When above application runs, following error ocurs.


     

    Above error basically explains that which component to be used for bootstrapping is not specified. We did not specified it because we did not know beforehand which component is to be bootstrapped. To manually bootstrap application, ngDoBoostrap method is to be added to the AppModule class.

     

    export class AppModule {
     ngDoBootstrap(app) { }
    }

     

    Before going on details of this method, we should know about "ApplicationRef". ApplicationRef is a reference to an angular application which is currently running on the page. So this ApplicationRef is passed to the ngDoBoostrap method and then for bootstrapping, the bootstrap method of the ApplicationRef is used for initializing root component.

     

    The app.module.ts is changed to:-

    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import { AppComponent } from './app.component';
    import { AdminComponent } from './admin/admin.component';
    import { UserComponent } from './user/user.component';
    import { Observable } from "rxjs"
    
    @NgModule({
     declarations: [
      AppComponent,
      AdminComponent,
      UserComponent
     ],
     imports: [
      BrowserModule
     ],
     entryComponents:[
      AdminComponent,UserComponent
     ],
     providers: []
    })
    export class AppModule {
     ngDoBootstrap(app) {
       fetchComponentSelector()
       .subscribe((name)=>{ bootstrapRootComponent(app, name)});
     }
    }
    
    // app - running application reference (ApplicationRef)
    // name - the component name(selector) to bootstrap
    function bootstrapRootComponent(app, name) {
    
     // define the possible bootstrap components with their selectors (html host elements)
     const options = {
      'app-admin': AdminComponent, //component selector act as key
      'app-user': UserComponent
     };
    
     // obtain reference to the DOM element and changing it's content
     const componentStatusElement = document.querySelector('#componentstatus');
     componentStatusElement.textContent = 'Loaded Component';
    
     // DOM element creation for bootstrapped component and finally adding it to DOM
     const componentElement = document.createElement(name);
     document.body.appendChild(componentElement);
    
     //selected component boostrap the application
     const component = options[name]; 
     app.bootstrap(component);
    }
    
    //To fetch component selector
    function fetchComponentSelector() {
     return new Observable((observer) => {
      setTimeout(() => { observer.next('app-admin');}, 2000);
     });
    }

     

    The bootstrapRootComponent function is responsible for bootstrapping selected root component. the fetchComponentSelector function is created to emulate HTTP request to the server and returns a selector within 2 seconds. This function is creating an observable by using the new Observable() call, then subscribed to by an observer, executed by calling the next(). next method just sends data to its subscribers.


    When an application runs, ngDoBootstrap method calls a fetchComponentSelector method, subscribing it. the fetchComponentSelector method returns "app-admin" selector making AdminComponent a root component and bootstrapping the application with it.

     

    Output :-

     

    Changing the selector in fetchComponentSelector to "app-user" will change root component to UserComponent and application will be bootstrapped with it.

     

    Output :

    Manual Bootstrapping of an Application - Angular 5

 0 Comment(s)

Sign In
                           OR                           
                           OR                           
Register

Sign up using

                           OR                           
Forgot Password
Fill out the form below and instructions to reset your password will be emailed to you:
Reset Password
Fill out the form below and reset your password: