Angular 2 notes

First credit to Deborah Kurata for her excellent course @ plural sight.

All my code is located here: github repo which is a cloned version from Deborah’s course code…  It is great for trying out new concepts!

Angular Modules

Every angular application has at least one module class which is the root module.   Of course that module is bootstrapped (in main.ts)  in order to run (launch) the application.

  1. They must be decorated with @NgModule  a metadata class decorator.
  2. Should be exported (public) so other component templates can use them
  3. Often import other modules
  4. Could provide services to any application component
  5. Aid in organization of application, often referred to as feature modules.  These are then imported into the root module

Quick Start Angular Application folder structure

QuickStart Angular folder structure inside the app folder

The application root module – AppModule

This module is used to tell Angular how the application is pieced together.  As noted earlier, all Angular applications must has at least one Angular Module.

Following conventions, its name is AppModule.  For step a step by step guide on how to create this manually, see this link.

Here is a most basic example as created from the QUICK-START app.

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';

@NgModule({
 imports: [ BrowserModule ],
 declarations: [ AppComponent ],
 bootstrap: [ AppComponent ]
})
export class AppModule { }

Here you will notice the Import statements which pull in resources the application will need.  Since I work with browser based applications my app.module.ts will almost always use the BrowserModule (more notes on it below).

NgModue observations

  1. This sets up the metadata used in the module.
  2. All metadata items are functions.
  3. NgModule is an interface with many options like: providers, declarations, imports, export and etc…
  4. For details on the module and the metadata options see this link.

BrowserModule

  1. Provides services for launching and running your application in a browser
  2. Re-Exports the CommonModule which provides access to Angular Directives (NgIf, NgFor…)

The BrowserModule provides services that are vitally important to run your application in a modern browser like chrome of I.E. Edge.

Note:  Do not import BrowserModule in any other module. Also you cannot lazy load this module.

After wiring up what is required we will will want to begin importing our actual application components.  For example, we import a component known as app.component.ts as generated in the quick-start files.

import { Component } from '@angular/core';

@Component({
 selector: 'my-app',
 template: '

{{title}}

‘, }) export class AppComponent { title = ‘Minimal NgModule’; }

This simply shows a title using a form of data binding known as string interpolation .  The value for the title comes from the exported class property title.

@NgModule

  1. You should notice in the app.module.ts the declarations and bootstrap metadata properties for NgModule have AppComponent in them.
  2. The declarations property list identifies the application’s only component, the root component.
  3. The bootstrap property is used to identify the AppComponent as the bootstrap component.  It is what kicks things off.

When an Angular application kicks off, it puts the HTML rendering of AppComponent in the DOM. In the quick start it is as defined in its @Component metadata selector.  For more info on the @Component decorator see this link.

The magic of Bootstrapping

So where does the actual bootstrapping occur?  Well, in most cases the index.html file will call the system.js.config.js file which in turn calls the main.ts (js) file when then kicks off the actual bootstrapping process.  If you are using a Angular Quickstart or CLI tool you will not need to worry about this for the vast majority of applications you will write in Angular.

Maybe an illustration will aid:

Angular Bootstrap process

Angular Bootstrap process

The above example is how the dynamic bootstrapping occurs. Which basically means the browser is shipped the Angular compiler  which then compiles our application in the browser.  For development or small applications this is fine.  But for performance you want to use the static bootstrapping method known as Ahead-Of-Time (AOT) Compilation.  Read more here about AOT.

Basic steps to adding a Component

First decide is this a stand alone component or will it be a nested component?

A stand alone will not have a selector property in the @Component metadata which a nested will need the selector defined.

I like to begin with an empty shell of a html file which will be our template.  I greatly prefer a html template over a inline template.

Naming convention for the file.

This will vary but I like to place my files in a folder that relates the purpose.  For example I am going to create a component that will list out a set of products.

So I create a folder called Products under the app folder.

Then I add a file called product-list.component.html

Then I add a product-list.component.ts file

In the product-list.component.ts file I will need a few basic things to kick the process off…

  1. create the class and besure to export it.
  2. Add the @Component decorator and them import it @angular/core
  3. Add the metadata needed.  Since the list is a root component it will not be nested, no selector is needed. But I will need a templateUrl and the moduleId decorator.
  4. Add an import for your data service if needed and include any services in the constructor.
  5. If you are going to respond to events you will need to include them from the core library.

Here is an example:

import { Component, OnInit } from '@angular/core';


import { IProduct } from './product';
import { ProductService } from './product.service';

@Component({
 // selector: 'pm-products', we are no longer nesting 
 moduleId: module.id,
 templateUrl: 'product-list.component.html',
 styleUrls: ['product-list.component.css']
})
export class ProductListComponent
 implements OnInit {
 //Image Properties
 imageWidth: number = 25;
 imageMargin: number = 2;
 showImage: boolean = false;

 pageTitle: string = 'Product Listing';
 listFilter: string;

 products: IProduct[];

 errorMessage: string;

 /** 
 * Long Contructor Method
 * private _productService: ProductService;
 *
 * constructor(productService: ProductService) {
 * this._productService = productService;
 * }
 */

 constructor(private _productService: ProductService) { }
 ngOnInit(): void {
 console.log('In OnInit');
 console.log('Module ID: ' + module.id);
 //this.products = this._productService.getProducts();
 this._productService.getProducts()
 .subscribe(products => this.products = products,
 error => this.errorMessage = error);
 }

 // Methods
 toggleImage(): void {
 this.showImage = !this.showImage;
 }
 onRatingClicked(message: string): void {
 this.pageTitle = 'Product List: ' + message;
 }
}

The Html Template

{{pageTitle}}
Filter by:

Filtered by: {{listFilter}}

ProductCodeAvailablePrice5 Star Rating
{{product.productName}}{{product.productCode}}{{product.releaseDate}}{{product.price | currency:’USD’:true:’1.2-2′}}

{{showImage ? ‘Hide’ : ‘Show’}} Image

Of course as your application grows you should use the angular module system to aid in organizing your code and help with lazy loading…

The product module code:

import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';

import { SharedModule } from '../shared/shared.module';
import { ProductService } from './product.service';
import { ProductListComponent } from './product-list.component';
import { ProductFilterPipe } from './product-filter.pipe';
import { ProductDetailComponent } from './product-detail.component';
import { ProductDetailGuard } from './product-guard-service';

import { ProductRoutingModule } from './product-routing.module';

@NgModule({
 declarations: [
 ProductListComponent,
 ProductDetailComponent,
 ProductFilterPipe
 ],
 imports: [
 SharedModule,
 ProductRoutingModule
 ],
 providers: [
 ProductService,
 ProductDetailGuard]
})
export class ProductModule {

}

This all of course must be wired up in the app.module.ts code in the app root folder…

Here is an example:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
//import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { RouterModule } from '@angular/router';

import {AppRoutingModule} from './app-routing.module';
import { AppComponent } from './app.component';
import { WelcomeComponent } from './home/welcome.component';
import { ProductModule } from './products/product.module';

@NgModule({
 imports: [BrowserModule,
 HttpModule,
 ProductModule,
 AppRoutingModule], // If you want to use # in your routes, set the following .forRoot([], {useHash: true}) - I think this is default for IIS7
 // directives, components and pipes by Angular, External or third party 
 declarations: [AppComponent, WelcomeComponent], // Our directives, components and pipes
 bootstrap: [AppComponent]
})
export class AppModule { }

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s