Angular *ngFor calling method multiple times problem

Background:
When using *ngFor directive try to avoid using methods inside the *ngFor loop.
When methods are used inside the *ngFor template databinding Angular triggers the method on every possible change detection. Angular does this because a method has side effects, its “impure”. Angular don’t know if the return value of the method has changed, and triggers a change detection check as often as possible.

Result:
If you set a console.log() inside your method that is called from within a *ngFor loop and tries to trigger some sort of change detection interaction (e.g. component init, click or mouse scroll depending on component implementation). You will see that the method is being triggered many more times than expected.

Example problem:
(heroes.component.html)

<ul class="heroes">
  <li *ngFor="let hero of heroes"
    [class.selected]="hero === selectedHero"
    (click)="onSelect(hero)">
    <h5>{{getHeroName(hero)}}</h5>
  </li>
</ul>

(heroes.component.ts)

getHeroName(hero: Hero) {
  console.log(hero.name);
  return hero.name;
}

The console.log will log 21 times on init and another 20 times for every “click”. The expected result is 10 console.logs upon init.

Above example could be fixed by instead calling the name property on the iterated variable (hero):

<ul class="heroes">
  <li *ngFor="let hero of heroes"
    [class.selected]="hero === selectedHero"
    (click)="onSelect(hero)">
    <h5>{{hero.name}}</h5>
  </li>
</ul>

Solution:
Use a property inside the *ngFor directive instead, so prepare a collection with correct data and save to properties instead of using methods. So the template will iterate over an already “prepared” model collection.

If call on method inside the *ngFor directive is hard to avoid, at least make sure the code is fast and is performant since it will be called many, many times in a row.

Source: https://www.reddit.com/r/Angular2/comments/59532r/function_being_called_multiple_times/

Angular – Stop mouse event propagation – Stack Overflow

If you want to be able to add this to any elements without having to copy/paste the same code over and over again, you can make a directive to do this. It is as simple as below:

import {Directive, HostListener} from “@angular/core”;
@Directive({
selector: “[click-stop-propagation]”
})
export class ClickStopPropagation
{
@HostListener(“click”, [“$event”])
public onClick(event: any): void
{
event.stopPropagation();
}
}

Then just add it to the element you want it on:

<div click-stop-propagation>Stop Propagation</div>

Source: angular – Stop mouse event propagation – Stack Overflow

Fixing Webstorm cant debug in Chrome error: “Please ensure that the browser was started successfully with remote debugging port opened”

Error message in Jetbrains Webstorm:

Waiting for connection to localhost:59066. Please ensure that the browser was started successfully with remote debugging port opened. Port cannot be opened if Chrome having the same User Data Directory is already launched.

Can be fixed by installing the “jetbrains ide” chrome extension and make sure the above settings checkbox is active “Use JetBrains IDE support extension…”

Using Renderer2 in Angular

The Renderer2 class is an abstraction provided by Angular in the form of a service that allows to manipulate elements of your app without having to touch the DOM directly. This is the recommended approach because it then makes it easier to develop apps that can be rendered in environments that don’t have DOM access, like on the server, in a web worker or on native mobile.

Source: Using Renderer2 in Angular

3 Ways to Pass Async Data to Angular 2+ Child Components ― Scotch.io

Let’s start with a common use case. You have some data you get from external source (e.g. by calling API). You want to display it on screen.However, instead of displaying it on the same component, you would like to pass the data to a child component to display.The child component might has some logic to pre-process the data before showing on screen.

Solution 1: Use *ngIf
Solution 2: Use ngOnChanges
Solution 3: Use RxJs BehaviorSubject

Source: 3 Ways to Pass Async Data to Angular 2+ Child Components ― Scotch.io

Angular: Tips. The importance of Pipes – codeburst

What we all like in Angular primarily is that it all mostly about templates. Templates are smart, dynamic, they use change detection to update themselves on a moment’s notice when a model is updated, the can manage HTML elements and nested components, enrich the markup with directives and make on-the fly data transformations, and the template syntax is amazing. The tools provided are vast and rich, but is it up to us to use them wisely.

Source: Angular: Tips. The importance of Pipes – codeburst