I just finished an Angular training, here some interesting related topics on Angular.

Visual code assistant

ctrl +; : pop the assistant in french keyboard

ctrl + . : pop the assistant in us keyboard

Section image

 

Command shortcuts

ng n projectName

ng g m moduleName

ng g c componentName

ng g p pipeName

ng g d directiveName

ng g g guardName

ng g s serviceName

Model

export class Iban{
    format: string;
    length: number;


    constructor(ibanData:Iban){
        Object.assign(this,{
            ...ibanData
        })
    }
}

Input decorator

Definition

 Input ( @Input() ) is one of the most used decorators in Angular apps. It is used to pass data from the parent or host component to the child component. This decorator has a relation with DOM property in the template where the child component is used.

Snippet

To define an input for a component, use the @Input decorator.

For example component needs a user argument to render information about that user:

So, you need to add an @Input binding to user:

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

@Component({ 

selector: 'user-profile',

 template: '{{user.name}}' 

}) 


export class UserProfile { 

@Input() user; 

constructor() {} 


}

Documentation

Use compodoc

Translation

Use ngx-translate

Hook onDestroy and memory leaks

One scenario where you are using Observable and subscribing it in a component and are getting a stream of data.

You should use ngOnDestroy and unsubscribe it when you leave the page to prevent the memory leak.

ngOnDestroy() {

  this.data.unsubscribe();
}

Output Decorator

Definition

@Output decorator is used to pass the data from child to parent component. @Output decorator binds a property of a component, to send data from one component to the calling component. @Output binds a property of the type of angular EventEmitter class.

Snippet

import { Component, Input, Output,EventEmitter, OnInit } from '@angular/core';  
  
@Component({  
   selector: 'app-student',  
   templateUrl: './student.component.html',  
   styleUrls: ['./student.component.css']  
})  
export class StudentComponent implements OnInit {  
   @Input() myinputMsg:string;  
   @Output() myOutput:EventEmitter<string>= new EventEmitter();  
   outputMessage:string="I am child component."  
   constructor() { }  
  
   ngOnInit() {  
      console.log(this.myinputMsg);  
   }  
}

In the output user-component

<app-student [myinputMsg]="myInputMessage" (myOutput) ="GetChildData($event)"></app-student>

Immutability on object

test(param:any):void{

  const val={...param};
  val.name="ok";
  return val;
  
}

Change detection

detectchange vs markforcheck

The biggest difference between the two is that detectChanges() actually triggers change detection, while markForCheck() doesn't trigger change detection.

Transclusion with ng-content

Form control and form group

Reactive forms provide a model-driven approach to handling form inputs whose values change over time. This guide shows you how to create and update a simple form control, progress to using multiple controls in a group, validate form values, and implement more advanced forms.

SCSS rather than CSS

Variable handling

// _variables.scss
// Colours
$g-color-blue: #509cf6;
$g-color-green: #1bb362;
$g-color-brand: $g-color-green;

// Font scale
$g-font-size: 16;
$g-font-size-large: 20;

syntax imbrications

//SCSS
.parent {
  color: red;


  .child {
    color: blue;
  }
}

Use of bootsrap and jquery

TrackBy in ngFor: performance lever

To refresh only the tracked items

Unit test with Jasmine

import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { UserComponent } from './user.component';
import { ReactiveFormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
import { UserListComponent } from './user-list/user-list.component';
import { UserItem } from './UserItem';


describe('UserComponent', () => {
  let component: UserComponent;
  // ComponentFixture is a test harness for interacting 
  //with the created component and its corresponding element.
  //
  //Access the component instance through the fixture 
  //and confirm it exists with a Jasmine expectation:
  let fixture: ComponentFixture<UserComponent>;


  beforeEach(async(() => {
    //initialization of the test environement
    TestBed.configureTestingModule({
      declarations: [ UserComponent ],
      // copy the imports from the module containing the component
      imports: [
        CommonModule,
        ReactiveFormsModule
     ]
    })
    .compileComponents();
  }));


  beforeEach(() => {
    fixture = TestBed.createComponent(UserComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });


  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('check user items array is empty', () => {
    expect(component.userItems).toEqual([]);
  });

  it('check adding of a user', () => {    
    const userIt: UserItem={
      firstname:'Bob',
      name:'Brown',
      email:'bbrown@unit.us'
    };
    component.addUser(userIt);
    expect(component.userItems.length).toEqual(1);
  });
});

Launch npm run test

Use several describe to group same functional matter tests

Use xdescribe and xit to deactivate bunch of tests or designated test

Routing

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { UserComponent } from './user/user.component';



const routes: Routes = [
  {
    path:'',
    redirectTo: '/user',
    pathMatch:'full'
  },{
    path:'user',
    component: UserComponent
  }


];


@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Guards protect application from user tricking the URL

No more "a href" with routes, use routerLink

Use the colon for parameters in route:

{
    path:'user/:id/edit',
    component: EditUserComponent
  
}

Debugging

use the chrome F12

use of localstorage

setItem(k,v)

getItem(k)

removeItem(k)

Trivial for primitives such as string, number

To handle array:

json.stringify

json.parse

visu in chrome F12>application>localstorage>file

Do not use localstorage for sensitive data because user can change it

Prime NG, AntDesign

To get components

HttpClient

Interceptors

For all the application

Do generic stuff

Used with

  1. requests
  2. scripts error
  3. parsing of JSON api

Promises dismissed for Observables

Three states: pending, resolved, rejected

Once a promised is reject or resolved, there are no way back

Promise thenable once the status is done.

It was designed to answer the callbacks hell.

Observables

subject (wait first change to load the data)

behaviorsubject (loads data at initialization)

subscribe and unsubscribe the memory death combo

operator pipe(take(1),filter({}))

pipe(map()) to transform values

forkjoin(list of observable like http requests) subscribe once all observable are triggered

Lazy loading

Do not import in the app module the lazy loading module

Declare the route of the lazy module as follows:

{
    path:'lazymodule',
    lazyChildren:'./lazymodule/lazymodule.module#LazyModule'

}

In the lazy module

Create a routing module dedicated to the routing of the lazy module

Import the routing module in the lazy module

Lazy load the modules not used frequently

Use preloadingStrategy:PreloadAllModules (on the app module) to trigger the lazy modules once the standard modules are loaded

Unit test on observables

Use mocks

Listen a property and return a fake dataset on that property

it('test obs',()=>{


spyOnProperty(component['userState'],'usersList')
     .and.returnValue(of([new User({nom:'brown',prenom:'bob', email:'bb@unit.us'})]));
component.ngOnInit();
expect(component.users.length).toEqual(1);

});