Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Typescript

Rewriting an Employee Tracker in Angular 2 and TypeScript – Part 1

3.00/5 (6 votes)
31 Jan 2017CPOL6 min read 12.6K  
This is the first part of Rewriting an Employee Tracker using Angular 2 and TypeScript Series.

This is the first part of Rewriting an Employee Tracker using Angular 2 and TypeScript Series.

The source code for this tutorial series is published on GitHub. Demo application is hosted in Microsoft Azure.

Part 1: Create an Angular 2 SPA in TypeScript

In previous tutorial series of building an Employee Tracker, we created the front end in Angular 1.5.5 and the back end in ASP.NET Web API 2.2.

In this tutorial, we will use Visual Studio Code to build the initial structure of the Angular 2 Single-Page Application (SPA) in TypeScript.

Client-Side Technologies:

The application structure, styles, and patterns follow the recommendations outlined in the official Angular 2 Style Guide

I use the official Angular 2 Developer Guide as a reference to write this tutorial series.

Prerequisites

The following are required to complete this tutorial:

  • Build the QuickStart app if you are new to Angular 2
  • Install Node.js and npm (Nods.js > 6.3.x and npm > 3.10.x) on your machine if you haven’t done so already

Task 1. Set up the Project Structure

I prefer to organize my project based on components/modules. Building a maintainable, scalable, and well-organized application should start from the beginning. Using DRY and SRP patterns, we will create smaller code files that each handle one specific job. This approach has helped me personally to locate, enhance, and debug requested features from clients quickly.

  1. Let’s creating folders and copying files to C:\_tutorials\ng2-employee-tracker from GitHub as listed below:

    ng2-employee-tracker                    // Project folder      
        |--api                              // test data
            |--dashboard.json   
            |--employees.json
        |--app
            |--dashboard                    // Dashboard feature module
                |--ng2-nvd3.ts              // nvd3             
            |--employees                    // Employees feature module
            |--layout                       // Layout component
        |--content                          
            |--css
                |--animate.css
                |--loading-bars.css
                |--sb-admin-2.css
            |--images
                |--favicon.ico
                |--loading-bars.svg
            |--js
                |--loading-bars.js
                |--sb-admin-2.js    
        |--package.json
        |--systemjs.config.js
        |--tsconfig.json
        |--typings.json
  2. Lines 21-24 list the package definition and configuration files:

    • package.json: defines scripts and serves as documentation for what packages the Employee Tracker depends on.
    • systemjs.config.js: loads application and library modules.
    • tsconfig.json: is a configuration file to guide the TypeScript compiler as it generates JavaScript files.
    • typings.josn: is a TypeScript definition file.

    See Add package definition and configuration files from 5 Minute QuickStart for explanations.

Task 2. Install the Packages

Open the terminal window, enter the npm install command to install all listed packages and libraries in package.json using npm.

Task 3. Create startup page

  1. Add the index.html file to the ng2-employee-tracker folder.

  2. Replace the code in this file with the following:

    <!DOCTYPE html>
    <html >
        <head>
            <!-- Set the base href -->
            <script>document.write('<base href="' + document.location + '" />');</script>
            <title>Angular 2 Employee Tracker App</title>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1">
    
            <!-- 1. Load css -->
            <link rel='stylesheet prefetch' href='node_modules/bootstrap/dist/css/bootstrap.min.css'>
            <link rel="stylesheet" href="content/css/sb-admin-2.css">
            <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.6.1/css/font-awesome.min.css" />
            <link rel="stylesheet" href="node_modules/nvd3/build/nv.d3.min.css"/>
            <link rel="stylesheet" href="content/css/animate.css" />
            <link rel="stylesheet" href="content/css/loading-bars.css" />
    
            <!-- 2. Load libraries -->
            <!--    2.1 Polyfill(s) for older browsers -->
            <script src="//cdnjs.cloudflare.com/ajax/libs/es6-shim/0.35.0/es6-shim.min.js"></script>
            <script src="node_modules/zone.js/dist/zone.min.js"></script>
            <script src="node_modules/reflect-metadata/Reflect.js"></script>
            <script src="node_modules/systemjs/dist/system.src.js"></script>
            <script src="node_modules/rxjs/bundles/Rx.min.js"></script>
            <!--        Fix the Date and Currency pipes in mobile safari -->
            <script src="//cdn.polyfill.io/v2/polyfill.min.js?features=Intl.~locale.en"></script>
    
            <!--    2.2 Vendor js libraries -->
            <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
            <script src="node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
            <script src="node_modules/d3/d3.min.js"></script>
            <script src="node_modules/nvd3/build/nv.d3.min.js"></script>
    
            <!-- 3. Configure SystemJS -->
            <script src="systemjs.config.js"></script>
            <script>
                System.import('app').catch(function(err) { console.error(err); });
            </script>
    
        </head>
    
        <body>
            <!-- 4. Display the application -->
            <employee-tracker-app>
                <!-- Show simple splash screen-->
                <div class="splash">
                    <div class="color-line"></div>
                    <div class="splash-title">
                        <h1>Angular 2 Employee Tracker</h1>
                        <img src="content/images/loading-bars.svg" width="64" height="64" title="" alt="" />
                    </div>
                </div>
            </employee-tracker-app>
        </body>
    </html>

    The index.html file serve as our startup page. It performs the following functions:

    • loads our resources (.css and .js)
    • configures SystemJS to load library modules and launch our application by running the AppModule in the main.ts file
    • renders our application’s component between the employee-tracker-app tags
    • shows our splash screen

Task 4. Bootstrap our application

  1. Add the main.ts file to the app folder.

  2. Replace the code in this file with the following:

    // The browser platform with a compiler
    import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
    
    // The app module
    import { AppModule }              from './app.module';
    
    // Compile and launch the module
    platformBrowserDynamic().bootstrapModule(AppModule);

    Line 8 bootstraps the imported AppModule from app.module.ts file using the Just in Time (JIT) complier to launch the application.

Task 5. Create the root module

By convention, every Angular app has a root module class called AppModule in app.module.ts file. The @NgModule decorator allows us to bundle components, services, pipes, and directives at the module level. If you want to learn more about the benefits of using @NgModule, please check out Rob Wormald’s blog post.

  1. Let’s add app.module.ts file to the app folder.

  2. Replace the code in this file with the following:

    import { NgModule }           from '@angular/core';
    import { BrowserModule }      from '@angular/platform-browser';
    import { HttpModule }         from '@angular/http';
    
    /* App Root */
    import { AppComponent }       from './app.component';
    import { SidebarComponent }   from './layout/sidebar.component';
    
    /* Feature Modules */
    import { DashboardModule }    from './dashboard/dashboard.module';
    import { EmployeesModule }    from './employees/employees.module';
    
    /* App Router */
    import { routing }            from './app.routing';
    
    @NgModule({
        imports:      [ BrowserModule, DashboardModule, EmployeesModule, HttpModule, routing ],
        declarations: [ AppComponent, SidebarComponent ],
        bootstrap:    [ AppComponent ]
    })
    
    export class AppModule {}
  3. Line 17 imports the following supporting modules whose exported components, directives, or pipes are referenced by the component declared in the AppModule.

    • BrowserModule: provides critical services that are essential to launch and run our app in the browser
    • DashboardModule: provides collections of Dashboard functionality
    • EmployeesModule: provides collections of Employees functionality
    • HttpModule: provides http services
    • routing: is a Router module which provides the application-wide configured services with routes in the root module
  4. Line 18 declares a list of components (AppComponent, SidebarComponent) that belong to the AppModule.

  5. Line 19 bootstraps the root component named AppComponent when Angular starts the application.

  6. Line 22 exports the AppModule so that the main.ts file can import it.

Task 6. Configure routes for the Router

The application will have one Router which enables navigation from one view to the next. To learn more about Routing & Navigation, please see the official doc here.

  1. Add the app.routing.ts file to the app folder.

  2. Replace the code in this file with the following:

    import { Routes, RouterModule } from '@angular/router';
    
    const appRoutes: Routes = [
        // 1st Route
        { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
        // 2nd Route
        { path: 'employees', redirectTo: '/employees' },
        // 3rd Route
        { path: '**', redirectTo: '/dashboard' }
    ];
    
    export const routing = RouterModule.forRoot(appRoutes, { useHash: true });

    We configure our Router with three routes:

    • 1st Route: when initial relative URL is empty (for example: http://localhost:3000) , redirect to another route whose path segment is /dashboard
    • 2nd Route: when URL matches the path segment /employees, redirect to another route whose path segment is /employees
    • 3rd Route: when URL doesn’t match any routes defined in our configuration, redirect to another route whose path segment is /dashboard

    We pass our three routes into the RouterModule.forRoot method which returns a module containing the configured Router. We export this module as the routing token.

    NOTE: We registered routing with the root module named AppModule.

Task 7. Create our root component and its view

  1. Add the root component named app.component.ts file to the app folder.

  2. Replace the code in this file with the following:

    import { Component } from '@angular/core';
    
    @Component ({
        selector: 'employee-tracker-app'
        ,templateUrl: 'app/app.component.html'
    })
    
    export class AppComponent {}

    The AppComponent is our application shell.

  3. Add the view named app.component.html file to the app folder.

  4. Replace the code in this file with the following:

    <div id="wrapper">
    
        <!-- Navigation Area -->
        <et-sidebar></et-sidebar>
        <!-- End Navigation Area -->
    
        <!-- Content Area -->
        <div id="page-wrapper">
    
            <!-- Routed View -->
            <router-outlet></router-outlet>
    
        </div>
        <!-- End Content Area -->
    
    </div>

    The app.component.html file contains the master layout for our HTML. It provides a shell with two regions: a navigation area and a content area. The navigation area renders the sidebar view between the et-sidebar tags. The content area uses router-outlet directive to display the views produced by the Router. In other words, when you click a navigation link, it’s corresponding view is loaded in the content area.

Task 8. Create the Sidebar component and its view

  1. Add the sidebar.component.ts file to the layout folder.

  2. Replace the code in this file with the following:

    import { Component } from '@angular/core';
    
    @Component ({
        selector: 'et-sidebar'
        ,templateUrl: 'app/layout/sidebar.component.html'
    })
    
    export class SidebarComponent {
        heading = 'Angular 2 Employee Tracker App';
    }

    The navigation area of the AppComponent uses et-sidebar to display the sidebar view.

  3. Add the view named sidebar.component.html file to the layout folder.

  4. Replace the code in this file with the following:

    <nav class="navbar navbar-default navbar-static-top" role="navigation" style="margin-bottom: 0">
        <!-- navbar-header -->
        <div class="navbar-header">
            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <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" href="#">{{heading}}</a>
        </div>
        <!-- /.navbar-header -->
    
        <!-- navbar-top-links -->
        <ul class="nav navbar-top-links navbar-right">
            <!-- dropdown envelope icon -->
            <li class="dropdown">
                <a class="dropdown-toggle" data-toggle="dropdown" href="#">
                     
                </a>
                <!-- dropdown-messages -->
                <ul class="dropdown-menu dropdown-messages">
                    <li>
                        <div class="text-center small">
                            You have 2 tutorials
                        </div>
                    </li>
                    <li class="divider"></li>
                    <li>
                        <a href="https://www.cc28tech.com/angular-2-employee-tracker-typescript-part-1" target="_blank">
                            <div class="small">
                                Part 1: 
                                <span class="text-info">
                                    Create an Angular 2 SPA in TypeScript
                                </span>
                            </div>
                        </a>
                    </li>
                    <li class="divider"></li>
                    <li>
                        <a href="https://www.cc28tech.com/angular-2-employee-tracker-typescript-part-2" target="_blank">
                            <div class="small">
                                Part 2: 
                                <span class="text-info">
                                    Create Angular 2 Feature Modules in TypeScript
                                </span>
                            </div>
                        </a>
                    </li>
                    <li class="divider"></li>
                    <li>
                        <a class="text-center text-info small" href="https://www.cc28tech.com" target="_blank">
                            <div class="text-info">
                                See Other Tutorials
                            </div>
                        </a>
                    </li>
                </ul>
                <!-- /.dropdown-messages -->
            </li>
            <!-- /.dropdown envelope icon -->
            <!-- dropdown user icon -->
            <li class="dropdown">
                <a class="dropdown-toggle" data-toggle="dropdown" href="#">
                     
                </a>
                <!-- dropdown-user -->
                <ul class="dropdown-menu dropdown-user">
                    <li>
                        <a href="https://www.cc28tech.com/cathy-wun" target="_blank">
                            <div class="text-center small">
                                 <span class="text-info">About Me</span>
                            </div>
                        </a>
                    </li>
                </ul>
                <!-- /.dropdown-user -->
            </li>
            <!-- /.dropdown user icon -->
        </ul>
        <!-- /.navbar-top-links -->
    
        <!-- navbar-static-side -->
        <div class="navbar-default sidebar" role="navigation">
            <!-- sidebar-collapse -->
            <div class="sidebar-nav navbar-collapse">
                <ul class="nav" id="side-menu">
                    <li>
                        <a routerLink="/dashboard" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }">
                            
                            <span class="nav-label">Dashboard</span>
                        </a>
                    </li>
    
                    <li>
                        <a routerLink="/employees" routerLinkActive="active">
                            
                            <span class="nav-label">Employees</span>
                        </a>
                    </li>
                </ul>
            </div>
            <!-- /.sidebar-collapse -->
        </div>
        <!-- /.navbar-static-side -->
    </nav>

    The sidebar.component.html uses Bootstrap for quick styling and building responsive layouts. It uses routerLink directive to represent navigation menu items.

  5. We have the following links in navigation menu:

    • Dashboard
    • Employees

    When you click the Dashboard link in the navigation menu, the Dasboard view will be placed in the content area of the AppComponent view:

    Clicking Dashboard menu

    When you click the Employees link in the navigation menu, the Employees view will be placed in the content area of the AppComponent view:

    Clicking Employees menu

In the next tutorial, we will build the Angular 2 Dashboard and Employees Feature Modules using TypeScript.

The source code for this tutorial series is published on GitHub. Demo application is hosted in Microsoft Azure.

References

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)