
ngFor to traverse arrays in templates, use this construct with the trackBy function, which returns a unique identifier for each element.trackBy , the system will know which element has changed and will make changes to the DOM that relate only to that particular element. Details about this can be found here . <li *ngFor="let item of items;">{{ item }}</li> // <li *ngFor="let item of items; trackBy: trackByFn">{{ item }}</li> // trackByFn(index, item) { return item.id; // id, } const .let and const keywords clarifies the intent regarding the use of entities declared with their help. In addition, this approach makes it easier to recognize problems caused by accidentally overwriting constant values. In such a situation, a compilation error is generated. In addition, it improves the readability of the code. let car = 'ludicrous car'; let myCar = `My ${car}`; let yourCar = `Your ${car}; if (iHaveMoreThanOneCar) { myCar = `${myCar}s`; } if (youHaveMoreThanOneCar) { yourCar = `${youCar}s`; } // car , car const car = 'ludicrous car'; let myCar = `My ${car}`; let yourCar = `Your ${car}; if (iHaveMoreThanOneCar) { myCar = `${myCar}s`; } if (youHaveMoreThanOneCar) { yourCar = `${youCar}s`; } import 'rxjs/add/operator/map'; import 'rxjs/add/operator/take'; iAmAnObservable .map(value => value.item) .take(1); import { map, take } from 'rxjs/operators'; iAmAnObservable .pipe( map(value => value.item), take(1) ); API_FIX (which resembles the TODO tag), and tag them with fixes. This makes finding such fixes easier. // <p>{{ textToDisplay }}</p> // iAmAnObservable .pipe( map(value => value.item), takeUntil(this._destroyed$) ) .subscribe(item => this.textToDisplay = item); // <p>{{ textToDisplay$ | async }}</p> // this.textToDisplay$ = iAmAnObservable .pipe( map(value => value.item) ); take , takeUntil and so on. iAmAnObservable .pipe( map(value => value.item) ) .subscribe(item => this.textToDisplay = item); takeUntil operator if you want to monitor changes in an object until another observed object generates a certain value: private destroyed$ = new Subject(); public ngOnInit (): void { iAmAnObservable .pipe( map(value => value.item) // iAmAnObservable takeUntil(this._destroyed$) ) .subscribe(item => this.textToDisplay = item); } public ngOnDestroy (): void { this._destroyed$.next(); } this is a pattern used to control the removal of subscriptions to many of the observed objects in a component.take if you only need the first value returned by the observed object: iAmAnObservable .pipe( map(value => value.item), take(1), takeUntil(this._destroyed$) ) .subscribe(item => this.textToDisplay = item); takeUntil with take . This is done in order to avoid memory leaks caused by the fact that the subscription did not result in a value before the component was destroyed. If the takeUntil function were not used takeUntil , the subscription would exist before the first value was received, but since the component would have already been destroyed, this value would never have been received, which would lead to a memory leak.switchMap when you need to ignore the previous dispatched action when a new action arrives.mergeMap if you need to handle all dispatched actions in parallel.concatMap when actions need to be processed one after another, in the order they are received.exhaustMap in situations where, during the processing of previously received actions, you need to ignore new ones. // app.routing.ts { path: 'not-lazy-loaded', component: NotLazyLoadedComponent } // app.routing.ts { path: 'lazy-load', loadChildren: 'lazy-load.module#LazyLoadModule' } // lazy-load.module.ts import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { RouterModule } from '@angular/router'; import { LazyLoadComponent } from './lazy-load.component'; @NgModule({ imports: [ CommonModule, RouterModule.forChild([ { path: '', component: LazyLoadComponent } ]) ], declarations: [ LazyLoadComponent ] }) export class LazyModule {} subscribe blocks of other monitored objects. Instead, use the appropriate operators to chain the commands together. Among such operators can be noted withLatestFrom and combineLatest . Consider the examples, and then comment on them. firstObservable$.pipe( take(1) ) .subscribe(firstValue => { secondObservable$.pipe( take(1) ) .subscribe(secondValue => { console.log(`Combined values are: ${firstValue} & ${secondValue}`); }); }); firstObservable$.pipe( withLatestFrom(secondObservable$), first() ) .subscribe(([firstValue, secondValue]) => { console.log(`Combined values are: ${firstValue} & ${secondValue}`); }); firstObservable , then the system will wait for the operation to complete, and only after that will work with the second observed object. If these objects are network requests, then it will look like synchronous execution of requests.any . const x = 1; const y = 'a'; const z = x + y; console.log(`Value of z is: ${z}` // Value of z is 1a y is a number here, but our program does not know about it, so it displays something that looks wrong, but does not give any error messages. Similar problems can be avoided by assigning appropriate types to variables and constants. const x: number = 1; const y: number = 'a'; const z: number = x + y; // : Type '"a"' is not assignable to type 'number'. const y:number public ngOnInit (): void { let myFlashObject = { name: 'My cool name', age: 'My cool age', loc: 'My cool location' } this.processObject(myFlashObject); } public processObject(myObject: any): void { console.log(`Name: ${myObject.name}`); console.log(`Age: ${myObject.age}`); console.log(`Location: ${myObject.loc}`); } // Name: My cool name Age: My cool age Location: My cool location myFlashObject object, the name of the property loc on location and made an error during code editing: public ngOnInit (): void { let myFlashObject = { name: 'My cool name', age: 'My cool age', location: 'My cool location' } this.processObject(myFlashObject); } public processObject(myObject: any): void { console.log(`Name: ${myObject.name}`); console.log(`Age: ${myObject.age}`); console.log(`Location: ${myObject.loc}`); } // Name: My cool name Age: My cool age Location: undefined myFlashObject , then in our case the system assumes that the value of the loc property of myFlashObject is undefined . She does not think that loc can be an invalid property name.myFlashObject object, then in a similar situation we will see, when compiling the code, a wonderful error message: type FlashObject = { name: string, age: string, location: string } public ngOnInit (): void { let myFlashObject: FlashObject = { name: 'My cool name', age: 'My cool age', // Type '{ name: string; age: string; loc: string; }' is not assignable to type 'FlashObjectType'. Object literal may only specify known properties, and 'loc' does not exist in type 'FlashObjectType'. loc: 'My cool location' } this.processObject(myFlashObject); } public processObject(myObject: FlashObject): void { console.log(`Name: ${myObject.name}`); console.log(`Age: ${myObject.age}`) // Property 'loc' does not exist on type 'FlashObjectType'. console.log(`Location: ${myObject.loc}`); } strict:true option in the tsconfig.json file to enable strict type checking.tslint.json file in order to organize the checking of code according to certain rules. public ngOnInit (): void { console.log('I am a naughty console log message'); console.warn('I am a naughty console warning message'); console.error('I am a naughty console error message'); } // . , : I am a naughty console message I am a naughty console warning message I am a naughty console error message // tslint.json { "rules": { ....... "no-console": [ true, "log", // console.log "warn" // console.warn ] } } // ..component.ts public ngOnInit (): void { console.log('I am a naughty console log message'); console.warn('I am a naughty console warning message'); console.error('I am a naughty console error message'); } // . console.log and console.warn console.error, Calls to 'console.log' are not allowed. Calls to 'console.warn' are not allowed. 
Source: https://habr.com/ru/post/425661/
All Articles