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

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
- requests
- scripts error
- 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); });