Monday 5 June 2017

Project Migration to Angular 2: Bootstrap Part 2

This article should be called Bootstrap Part 1 rewinded, because, in the mean time i did move from Angular 2 and Angular-Seed to Angular 4 and Angular CLI.

I still want to integrate Bootstrap as a JQuery/Javascript library. I start using the application I described in my previous article about the deployment of Angular Applications.

Bootstrap

Adding Bootstrap and jQuery is straight forward:
. . .,
  "dependencies": {
    . . .,
    "@angular/router": "~4.1",
    "bootstrap": "^3.3.0",
    "core-js": "^2.4.1",
    "jquery": "^3.0.0",
    . . .
  }
  . . .
Install Bootstrap and JQuery executing npm install at the prompt. Now bootstrap has to be added to the application:
. . .,
  "apps": [
    {
      . . . ,
      "styles": [
        "../node_modules/bootstrap/dist/css/bootstrap.css",
        "../node_modules/bootstrap/dist/css/bootstrap-theme.css",
        "styles.css"
      ],
      "scripts": [
        "../node_modules/bootstrap/dist/js/bootstrap.js"
      ],
      . . .
      }
    }
  ],
  . . .

JQuery

JQuery may be added the same way as the bootstrap.js script, but the application throws an exception if packaged with Electron. To avoid this issue JQuery has to be added as external Javascript:
<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>MyProject</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>
  <sd-app>Loading...</sd-app>
  <!-- added for compatibility with Electron see https://github.com/electron/electron/issues/254#issuecomment-183483641. -->
  <script type="text/javascript">if (typeof module === 'object') {window.module = module; module = undefined;}</script>
  <script type="text/javascript" src="assets/js/jquery.min.js"></script>
  <script type="text/javascript">if (window.module) module = window.module;</script>
</body>
</html>
The disadvantage is when JQuery is updated by npm install doesn't automatically get updated into the application. I added the command jquery to be executed after install to avoid this problem.
...,
  "scripts": {
    ...,
    "jquery": "copy node_modules\\jquery\\dist\\jquery.min.js src\\assets\\js"
  },...

Navigation

I add a navigation bar to the application:
prompt > cd src/app/shared
prompt > ng generate module navbar
to check if bootstrap works.
nav a {
  color: #8f8f8f;
  font-size: 14px;
  font-weight: 500;
  line-height: 48px;
  margin-right: 20px;
  text-decoration: none;
  vertical-align: middle;
  cursor: pointer;
}

nav a.router-link-active {
  color: #106cc8;
}
<header class="bs-nav navbar navbar-inverse navbar-static-top">
  <div class="container-fluid">
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-navbar-collapse-1" aria-expanded="false">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" [routerLink]="['/']">MyApplication</a>
    </div>
    <div class="collapse navbar-collapse" id="bs-navbar-collapse-1">
      <ul class="nav navbar-nav">
        <li [routerLinkActive]="['active']" [routerLinkActiveOptions]="{exact:true}"><a [routerLink]="['/']">Home<span class="sr-only">(current)</span></a></li>
        <li [routerLinkActive]="['active']" [routerLinkActiveOptions]="{exact:true}"><a [routerLink]="['/about']">About</a></li>
      </ul>
    </div>
  </div>
</header>
import { Component } from '@angular/core';

/**
 * This class represents the navigation bar component.
 */
@Component({
  moduleId: module.id,
  selector: 'sd-navbar',
  templateUrl: 'navbar.component.html',
  styleUrls: ['navbar.component.css'],
})
export class NavbarComponent { }
import { ModuleWithProviders, NgModule } from '@angular/core';
import { CommonModule }                  from '@angular/common';
import { RouterModule }                  from '@angular/router';

import { NavbarComponent }               from './navbar/navbar.component';

@NgModule({
  imports: [
    CommonModule,
    RouterModule
  ],
  declarations: [NavbarComponent],
  exports: [NavbarComponent]
})
export class SharedModule {
  static forRoot(): ModuleWithProviders {
    return {
      ngModule: SharedModule,
      providers: []
    }
  }
}
<sd-navbar></sd-navbar>
<router-outlet></router-outlet>
import { Component } from '@angular/core';

@Component({
  selector: 'sd-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {}
import { BrowserModule } from '@angular/platform-browser';
import { NgModule }      from '@angular/core';
import { FormsModule }   from '@angular/forms';
import { HttpModule }    from '@angular/http';

import { AboutModule }     from './about/about.module';
import { AppComponent }    from './app.component';
import { AppRoutingModule} from './app-routing.module';
import { HomeModule }      from './home/home.module';
import { SharedModule }    from './shared/shared.module';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    AboutModule,
    AppRoutingModule,
    BrowserModule,
    FormsModule,
    HomeModule,
    HttpModule,
    SharedModule.forRoot()
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
Not very spectacular, but it works and Electron doesn't fire an exception loading the Bootstrap plug-ins. The code of the application is available on Github.


No comments:

Post a Comment