Angular 4 Fundamentals

Angular 4 Fundamentals

Modules

  • NgModules help organize an application into cohesive blocks of functionality.
  • Any class with a decorator function of @NgModule({ ... })
  • Every app must have at least 1 module
  • Modules are “packages” written for specialized tasks. Angular ships with its own modules like BrowserModule, HttpModule and FormsModule. One can also create his own module.
  • The conventional name for the main angular module is “AppModule”
  • Per [Angular’s architecture diagram](https://angular.io/guide/architecture), a module can contain a component, service, value or a function
  • Goes into the “imports” argument of the @NgModule decorator

Components

  • Class that controls a view
  • Lifecycle Hooks in Order
    • constructor
    • ngOnChanges
    • ngOnInit
    • ngDoCheck
    • ngDoAfterContentInit
    • ngDoAfterContentChecked
    • ngAfterViewInit
    • ngAfterViewChecked
    • ngOnDestroy
  • This is equivalent to .NET web forms code-behind page
  • Recommended for strong typing on editors that support it but not required is for a component to implement the hook interface. The name of the interface is the same as the hook minus the “ng” prefix. For example a component that needs to use the ngOnInit hook should be written as `Component1 implements OnInit`.
  • Use case for every hook [https://angular.io/guide/lifecycle-hooks](https://angular.io/guide/lifecycle-hooks)
  • Goes into the “declarations” argument of the @NgModule decorator
@HostBinding - sets a property to the host element which is the custom HTML tag specified in the `selector` (host) component property
export class ArticleComponent implements OnInit {
  @HostBinding('attr.class') cssClass = 'row';
  ...
@HostListener - allows you to subscribe to the events of the DOM element.
@HostListener('click') displayMessage(): void {
  alert(this.message);
}

Talking to the DOM directly is not considered best practice @HostListener will be triggered for every HTML element if you have multiple root nodes in your templates like below

<div>...</div>
<i>..</i>

Content projection using ng-content allows you to inject dynamic markup in your template

// component file 
@Component({
  selector: 'home',
  template: `
    <h1>Title</h1>
    <ng-content></ng-content>
  `
})

// templateUrl file
<home>
  <p>Hello World</p>
</home>

Component Lifecycle Hooks in order of execution:

  • OnChanges
  • OnInit
  • DoCheck
  • AfterContentInit
  • AfterContentChecked
  • AfterViewInit
  • AfterViewChecked
  • OnDestroy
  • OnChanges is called every time a component’s @Input property changes
  • DoCheck checks for any component property. Use this for changes that Angular wouldn’t catch like nested object properties. Avoid using OnChanges and DoCheck together because you’ll be calling 2 hooks for every change.
  • OnChanges, DoCheck, AfterContentChecked, and AfterViewChecked are all called every change detection
Angular’s default change detection uses the Zones library
  • Angular has a top-down execution for change detection. A component change anywhere in a dependency tree will trigger change detection for the entire tree.

Angular offers Default and OnPush ChangeDetectionStrategy for component bindings

Templates

The component's view
  • Where markup resides
  • Component inside a component is represented as a custom HTML tag
  • Follows a mustache syntax
  • Template syntax: https://angular.io/guide/template-syntax
  • Can be inline inside a component using the “template” argument or an external file using the “templateUrl” argument
  • Recommended that templates are relative to components for AOT compilation

Metadata

Tells Angular how to process a class
  • Metadata is set in the form of decorators. A component class is nothing more than a class if without a metadata information. Using the @Component decorator on a component class, you can point where the the template is located and what custom tag to use like below
@Component({
  selector:    'hero-list',
  templateUrl: './hero-list.component.html',
  providers:  [ HeroService ]
})
export class HeroListComponent implements OnInit {
/* . . . */
}

Data Binding

  • Push/pull data mapping between template and the component members
  • 4 syntax forms
    • {{ value }} : component property binding, outputs to the DOM
    • [property]=“value” : component property binding for passing “value” down to a child component for outputting to the DOM
    • (event)=“functionName(argument)” : event binding for calling a component function
    • [(ngModel)]=”model.property” : event and property binding useful for form submissions
@Input - allows data to flow from the binding expression (template) into the directive (component).
  • If you need to pass a value/object from the template into the component class, add a property to the template that matches the component class member. Whatever value you set will now be available inside the component class

Template:

<!-- myapp.component.html -->
<myapp [myData]="myDataModel"></myapp>

Component Class:

export class MyAppComponent {
  // this is now available everywhere in this class
  @Input() myData: MyDataClass
}
  • brackets denote input. The value you assign to it will be used by the component property
@Output - expose event producers, such as EventEmitter objects. An output property streams an event “out” of the component
  • Native events such as click and keyup can be easily handled like so
<!-- Template -->
<button (click)="decrease()">Decrease</button>

<!-- Component -->
export class MyAppComponent {
  click():void { return ‘hello’; }
}
  • parenthesis denote output. This sends data out of your component for other components to listen to. These are your event handlers
  • If you want to send a custom event when a DOM action is triggered, you have to use EventEmitter. You set it up inside your component. You then listen for a native event and call the EventEmitter.emit() method after to broadcast it.

Template for MyComponent

<button (click)=”clickHandler” />

MyComponent

@Component({ selector: ‘my-component’ })
export class MyComponent {
  clickCount: number = 0;
  @Output() onEvent = new EventEmitter<number>();
  clickHandler():void{
    onEvent.emit(clickCount++);
  }
...

OtherComponent

@Component({ 
  selector: `other-component`,
  template: `
    <div>
      <my-component (onEvent)=otherCompHander($event) />
    </div>
  `
})
export class OtherComponent({
  otherCompHandler(count:number):void{
    console.log(count);
  }
})

Directives

  • Provides instructions on how to transform the DOM
  • Directives are classes with a @Directive decorator
  • 3 types of Directives
    • Components - under the hood it has a @Directive extended to have template features
    • Structural - changes the layout
    • Attribute - changes the appearance
  • Built-in attribute directives:
NgClass for adding or deleting css classes
<p [ngClass]=”component.propery” />
NgStyle for inline styling
<p [ngStyle]=”component.property” />
NgModel for data binding
<input [(ngModel)]="component.property">
Common built-in structural directives:
NgIf to remove an element or guard against null
<div *ngIf="currentHero">...</div>
NgFor as a looping construct
<div *ngFor="let hero of heroes">...</div>
NgSwitch as an alternative to NgIf
https://angular.io/guide/template-syntax#the-ngswitch-directives 
@Directie exportAs property - allows you to reference a DOM element in your template like a local variable
// needs a  selector
@Directive({exportAs: ‘popup’, template:`
<b #popup1=”popup” message=”1” />
<b #popup2=”popup” message=”2” />
<a (click)=”popup1.print()” />
<a (click)=”popup2.print()” />
`})
export class PopupDirective{
  @Input() message;
  @HostListener(‘click’) print(){console.log(message)}
}

Services

  • Broad category encompassing any value, function, or feature that your application needs.
  • Anything can be a service
  • Should do one thing well
  • A class that focuses on doing a single thing like a logger service or a data service.
  • Utility classes or libraries that can be passed into components
  • Goes into the “providers” argument of the @NgModule or @Component decorators
  • Requires @Injectable decorator

Dependency Injection

  • A way to supply class dependencies through the constructor
  • Most dependencies are services
  • The typical case is to use the “providers” argument at the module level. Angular will resolve uninstantiated services if it hasn’t been used.
  • Passing services at the module level ensures you’re working with the same instance of the class everywhere down to the module’s components
  • Passing services at the component level means you get a new instance of it every time the component is created

Routing

Dependencies:

  • ‘@angualr/router’ module
  • template
  • [routerLink] attribute
  • OR { provide: APP_BASE_HREF, useValue: '/' } as a provider
  • You’ll typically import {RouterModule, Routes, ActivatedRoute} from @angular/module
  • <router-outlet /> in your view is where the route components will be rendered. You can have multiple router outlets in your view with a caveat that it has to have a name attribute that you can target in your route configuration.
  • [routerLink]=[‘/about’] is a directive you can use in your Anchor tags to resolve the url of your application. Note that the value of routerLink is an array for additional parameters like in cases where the url is parameterized.
  • The base href section is used for links with relative paths

Url Parsing strategies:

  • HashLocationStrategy - hash url style
  • PathLocationStrategy - html5 default using pushState

Sample Code:

  @NgModule({
    ...
    providers: [
      { provide: LocationStrategy, useClass: HashLocationStrategy },
      { provide: APP_BASE_HREF, useValue: '/' } // <--- this right here
    ]
  })
Import ActivatedRoute for handling dynamic urls and query string parameters.
  • Use activatedRoute.params[‘id’] to get the values from a route like /product/:id
  • Use activatedRoute.queryParamMap( params => params.get(‘key’ ) for querystring parameters
Import `CanActivate` from ‘@angular/router` for restricted routes

Guarding routes that are behind a login can be configured as { path: ‘admin’, component: ‘’, canActivate: [ LoggedInGuard ] }, where the authentication class structure looks like below

@Injectable()
export class LoggedInGuard implements CanActivate {
  canActivate(
    ...
  }
}

Observables

  • Application of the Observer and Iterator pattern
  • An observer subscribes to an Observable. An Observable emits items or sends notifications to its observers by calling the observers’ methods - next, error and complete.
  • Angular moved from Promises to Observables because the former lacks retry and cancellation mechanisms
  • An observable remains unhandled until an element subscribes to it
Outputting data to the template: https://auth0.com/blog/making-use-of-rxjs-angular/
  • When dealing with an Observable say for an AJAX request, you can use the async pipe to output the Observable value in your template. It will update the template once data has been extracted from the Observable
  • The alternative is to subscribe to the Observable, inside the callback function you can grab the value and assign it to your component property
Hot or Cold Observable
  • In the context of an AJAX request if you have 3 subscribes to an Observable, the AJAX request will issue 3 network calls (Cold Observable). To avoid doing this if you only need 1 network request, call the share() method (Hot Observable) to limit it.

Ahead of Time Compilation

  • Faster rendering
  • Fewer asynchronous requests
  • Smaller angular app download size
  • Errors are caught at compile time
  • Slow development time. The recommended compilation strategy for now is JIT in development and AOT in production
  • https://angular.io/guide/aot-compiler
  • Requires the “@angular/compiler-cli” to be installed, where the ngc command becomes a replacement for tsc
  • You can use tree-shaking libraries like rollup to remove dead dependencies for further file size optimization

Injectables

  • @Injectable marks a class as available to an injector for instantiation
  • Decorator that allows services to be consumed by other modules
  • @Component, @Directive, @Pipe are subtypes of @Injectable

Pipes

Pipes - a way to write display-value transformations that you can declare in your HTML.
  • Filters in Jinja
  • Allows for data transformations in the template
  • Boilerplate Code for Custom Pipe
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
  name: 'toFriendlyDuration'
})
export class MyPipe implements PipeTransform {
  transform(value: string, args?: any[]): any {}