Setup Virtual Machine for testing browser Microsoft Edge version 18

I needed to test a locally developed website in old legacy browser Microsoft Edge version 18. My system is Windows 10 using Oracle VM VirtualBox software.

Here is how to setup the Virtual Machine for accessing an Angular website on the “localhost” hostname. The website also makes requests to a localhost Java based REST API. E.g. upon entering http://localhost:4200 in the VM it should work the same as in the host OS.

Download Edge Virtual Machine

VirtualBox software: Oracle VM VirtualBox software
Edge Image: https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/
Use the “Virtualbox” VM image.
Direct link:
https://az792536.vo.msecnd.net/vms/VMBuild_20190311/VirtualBox/MSEdge/MSEdge.Win10.VirtualBox.zip
The VM password is: Passw0rd!

Make Angular development server available as “localhost” in the VM

Setup network:
In Oracle VM VirtualBox -> Settings -> network -> Attached to: “NAT”

Advanced -> port forwarding:
Name:”Angular server”, Protocol: TCP, Host port: 4200, Guest port: 4200
(dont set host and guest IP)

The above makes the Angular web development server (ng serve) available on http://localhost:4200 in the VM.

Make a Java Spring backend API available as “localhost” in the VM

(In the VM environment)
Add to the c:\windows\system32\drivers\etc\hosts file:

10.0.2.2 outer

The above config tells the VM OS to expose all requests of 10.0.2.2 to the “outer” hosting machine.

(In the VM environment)
Start an elevated cmd and enter this:

netsh interface portproxy add v4tov4 listenaddress=127.0.0.1 listenport=8081 connectaddress=10.0.2.2 connectport=8081

The above command will forward all requests for localhost:8081 to 10.0.2.2:8081 (which the hosts file made available for the “outer” host OS).

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/

Making games: Where do I start? – Game Code School

So you want to make a game? Games can be powerful! To the gamer they can entertain, motivate, educate, persuade. They can cause visceral feelings like excitement, happiness, sadness and even fear. To you, the creator/programmer/designer, making games can give immense satisfaction and personal advancement, perhaps even fame and wealth.

Source: Making games: Where do I start? – Game Code School

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…”

Internet Explorer 11 and Angular 2+ – Agilix – Medium

IE 11 and Angular don’t always mix. I must say that there’s quite the support provided by the Angular dev team and community. But, there are things that really aren’t up for the Angular devs to fix.

I’ve created a small list of issues I’ve encountered when developing and Angular 5 application for an IE 11 client.

Source: Internet Explorer 11 and Angular 2+ – Agilix – Medium

Javascript debugging helper – Count number of eventlisteners in Chrome console

Paste and run one of the code blocks below in chrome console to get eventlisteners count.

//eventlisteners counter - grouped summary
Array.from(document.querySelectorAll('*'))  .reduce(function(pre, dom){
    var evtObj = getEventListeners(dom)
    Object.keys(evtObj).forEach(function (evt) {
      if (typeof pre[evt] === 'undefined') {
        pre[evt] = 0
      }
      pre[evt] += evtObj[evt].length
    })
    return pre
  }, {})
  
//_-------------------------------------------
  
  // //eventlisteners - totalcount
  var totalCount = 0;
  Array.from(document.querySelectorAll('*')).reduce(function(pre, dom){
    var evtObj = getEventListeners(dom)
    Object.keys(evtObj).forEach(function (evt) {
      if (typeof pre[evt] === 'undefined') {
        pre[evt] = 0
      }
      // pre[evt] += evtObj[evt].length
	  totalCount += evtObj[evt].length;
    })
    return totalCount;
  }, {})
  
  
  //---------------------------------------