Injecting Services into Services in Angular

app.module.ts

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

import {AppComponent} from './app.component';
import {Logging2Service} from './logging2.service';
import {DataService} from './data.service';

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

logging2.service.ts

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

@Injectable({
  providedIn: 'root'
})
export class Logging2Service {

  constructor() {
  }

  logStatus(status: string) {
    console.log('Status : ' + status);
  }
}

data.service.ts

import {Injectable} from '@angular/core';
import {Logging2Service} from './logging2.service';

@Injectable({
  providedIn: 'root'
})
export class DataService {

  constructor(private loggingService: Logging2Service) {
  }

  addNewData(name: string, age: number) {
    // insert data to db
    // db.insert(name,number);

    this.loggingService.logStatus('New');
  }
}

References
https://github.com/mhdr/AngularSamples/tree/master/019/my-app

Creating a Logging Service in Angular

logging2.service.ts

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

@Injectable({
  providedIn: 'root'
})
export class Logging2Service {

  constructor() {
  }

  logStatus(status: string) {
    console.log('Status : ' + status);
  }
}

app.component.ts

import {Component} from '@angular/core';
import {Logging2Service} from './logging2.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  providers: [Logging2Service]
})
export class AppComponent {

  constructor(private loggingService: Logging2Service) {
  }

  onButtonClick() {
    this.loggingService.logStatus('New');
  }
}

app.component.html

<input type="button" (click)="onButtonClick()" value="Log"/>

Above we injected the service to component level so we can have different instances of service for different components, but we can have the service on app level by initializing it in app.module.ts (we should remove it from component providers). On this case, all instances of service in the application share the same data.

app.module.ts

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

import { AppComponent } from './app.component';
import {Logging2Service} from './logging2.service';

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

 

Reference
https://github.com/mhdr/AngularSamples/tree/master/019/my-app
https://angular.io/guide/hierarchical-dependency-injection
https://itnext.io/understanding-provider-scope-in-angular-4c2589de5bc

Understanding ngSwitch in Angular

app.component.ts

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  number = 10;
}

app.component.html

<div [ngSwitch]="number">
  <p *ngSwitchCase="1">1</p>
  <p *ngSwitchCase="2">2</p>
  <p *ngSwitchCase="10">10</p>
  <p *ngSwitchDefault>Default</p>
</div>

References
https://github.com/mhdr/AngularSamples/tree/master/018/my-app

Building a Structural Directive in Angular

unless.directive.ts

import {Directive, Input, TemplateRef, ViewContainerRef} from '@angular/core';

@Directive({
  selector: '[appUnless]'
})
export class UnlessDirective {

  @Input() set appUnless(condition: boolean) {
    if (!condition) {
      this.vcRef.createEmbeddedView(this.templateRef);
    } else {
      this.vcRef.clear();
    }
  }

  constructor(private templateRef: TemplateRef<any>, private vcRef: ViewContainerRef) {
  }

}

app.component.html

<P *appUnless="true">True</P>
<P *appUnless="false">False</P>

References
https://github.com/mhdr/AngularSamples/tree/master/017/my-app

Binding to Directive Properties in Angular

binding2.directive.ts

import {Directive, HostBinding, HostListener, Input, OnInit} from '@angular/core';

@Directive({
  selector: '[appBinding2]'
})
export class Binding2Directive implements OnInit {

  @Input() defaultColor = 'transparent';
  @Input() highlightColor = 'yellow';

  @HostBinding('style.backgroundColor') backgroundColor = 'transparent';

  constructor() {
  }

  @HostListener('mouseenter') mouseover(eventData: Event) {
    this.backgroundColor = this.highlightColor;
  }

  @HostListener('mouseleave') mouseleave(eventData: Event) {
    this.backgroundColor = this.defaultColor;
  }

  ngOnInit(): void {
    this.backgroundColor = this.defaultColor;
  }
}

app.component.html

<p appBinding2 [defaultColor]="'purple'" [highlightColor]="'orange'">Hello World 5</p>

References
https://github.com/mhdr/AngularSamples/tree/master/015/my-app

Using HostBinding to Bind to Host Properties when Creating Directive in Angular

host-binding.directive.ts

import {Directive, HostBinding, HostListener} from '@angular/core';

@Directive({
  selector: '[appHostBinding]'
})
export class HostBindingDirective {

  @HostBinding('style.backgroundColor') backgroundColor = 'transparent';

  constructor() {
  }

  @HostListener('mouseenter') mouseover(eventData: Event) {
    this.backgroundColor = 'green';
  }

  @HostListener('mouseleave') mouseleave(eventData: Event) {
    this.backgroundColor = 'transparent';
  }
}

app.component.html

<p appHostBinding>Hello World 4</p>

References
https://github.com/mhdr/AngularSamples/tree/master/015/my-app

Using HostListener to Listen to Host Events when Creating Directive in Angular

host-listener.directive.ts

import {Directive, ElementRef, HostListener, OnInit, Renderer2} from '@angular/core';

@Directive({
  selector: '[appHostListener]'
})
export class HostListenerDirective implements OnInit {

  constructor(private elementRef: ElementRef, private renderer: Renderer2) {
  }

  ngOnInit(): void {
  }

  @HostListener('mouseenter') mouseover(eventData: Event) {
    this.renderer.setStyle(this.elementRef.nativeElement, 'background-color', 'green');
  }

  @HostListener('mouseleave') mouseleave(eventData: Event) {
    this.renderer.setStyle(this.elementRef.nativeElement, 'background-color', 'transparent');
  }

}

app.component.html

<p appHostListener>Hello World 3</p>

References
https://github.com/mhdr/AngularSamples/tree/master/015/my-app

Creating an Attribute Directive in Angular

basic-highlight.directive.ts

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

@Directive({
  selector: '[appBasicHighlight]'
})
export class BasicHighlightDirective implements OnInit {

  constructor(private elementRef: ElementRef) {
  }

  ngOnInit(): void {
    this.elementRef.nativeElement.style.backgroundColor = 'red';
  }

}

better-highlight.directive.ts

Using the Renderer to build a Better Attribute Directive

import {Directive, ElementRef, OnInit, Renderer2} from '@angular/core';

@Directive({
  selector: '[appBetterHighlight]'
})
export class BetterHighlightDirective implements OnInit {

  constructor(private elementRef: ElementRef, private renderer: Renderer2) {
  }

  ngOnInit(): void {
    // use this in environments that DOM is not directly accessible like cordova apps
    this.renderer.setStyle(this.elementRef.nativeElement, 'background-color', 'blue');
  }

}

app.component.html

<p appBasicHighlight>Hello World</p>
<p appBetterHighlight>Hello World 2</p>

References
https://github.com/mhdr/AngularSamples/tree/master/016/my-app

Understanding the Component Lifecycle in Angular

ngOnChanges() Respond when Angular (re)sets data-bound input properties. The method receives a SimpleChanges object of current and previous property values.

Called before ngOnInit() and whenever one or more data-bound input properties change.

ngOnInit() Initialize the directive/component after Angular first displays the data-bound properties and sets the directive/component’s input properties.

Called once, after the first ngOnChanges().

ngDoCheck() Detect and act upon changes that Angular can’t or won’t detect on its own.

Called during every change detection run, immediately after ngOnChanges() and ngOnInit().

ngAfterContentInit() Respond after Angular projects external content into the component’s view / the view that a directive is in.

Called once after the first ngDoCheck().

ngAfterContentChecked() Respond after Angular checks the content projected into the directive/component.

Called after the ngAfterContentInit() and every subsequent ngDoCheck().

ngAfterViewInit() Respond after Angular initializes the component’s views and child views / the view that a directive is in.

Called once after the first ngAfterContentChecked().

ngAfterViewChecked() Respond after Angular checks the component’s views and child views / the view that a directive is in.

Called after the ngAfterViewInit() and every subsequent ngAfterContentChecked().

ngOnDestroy() Cleanup just before Angular destroys the directive/component. Unsubscribe Observables and detach event handlers to avoid memory leaks.

Called just before Angular destroys the directive/component.

References
https://angular.io/guide/lifecycle-hooks