Using Diffusion with Angular

Angular is one of the most popular JavaScript front-end frameworks used today, allowing developers to quickly build modern web applications using TypeScript. The Diffusion JavaScript client is delivered complete with TypeScript definitions, but there are a couple of configuration steps to be taken before it can be used seamlessly with Angular. If you are new to Diffusion or Angular, we recommend reading through the Diffusion Quick Start Guide and the Angular Quick Start Guide first.

This guide will help you set up an Angular+Diffusion app from scratch, guiding you past some of the hurdles you may come across along the way.

Note that this guide was tested with Angular 7.0.2 with Diffusion. We recommend you use Angular 7, as there are known compatibility issues with Angular versions 6 and 8.

Set Up

Create a new project with the ng cli:

ng new DiffusionAngular

hitting Enter to accept the default for all prompts.

This will create a new directory named DiffusionAngular/ and set up a new Angular project inside of it. When the initialization is complete, cd into the DiffusionAngular/ directory, and run:

npm i -P diffusion

to install the latest release of the Diffusion JavaScript client. This includes the TypeScript definitions which we will make use of in the Angular project.

Out of the box, this will throw warnings when building, due to the default Angular webpack configuration lacking the required Node.js shims to pack the Diffusion JavaScript client. We will make use of a custom builder in order to add some additional webpack configuration. Run:

npm i -D @angular-builders/custom-webpack @angular-builders/dev-server

to install the custom builders.

Configuration

To use the custom webpack builder, modify your angular.json configuration to change the @angular-devkit/build-angular:browser builder to @angular-builders/custom-webpack:browser and add a custom webpack configuration file:

...
"architect": {
"build": {
"builder": "@angular-builders/custom-webpack:browser",
"options": {
"customWebpackConfig": {
"path": "webpack.config.js"
},
...
}
...
}
...
}
...

Then create a new file called webpack.config.js containing the following:

module.exports = {
node: {
global: true,
buffer: true,
process: true,
zlib: true
}
};

This will instruct webpack to include shims for each of these node libraries.

To use ng serve when developing your app, you will also need to modify the serve builder:

For Angular 7

...
"architect": {
...
"serve": {
"builder": "@angular-builders/dev-server:generic"
...
}
...
}
...

For Angular 8+

...
"architect": {
  ...
  "serve": {
  "builder": "@angular-builders/custom-webpack:dev-server"
  ...
  }
  ...
}
...

Using Diffusion

Now that we have Diffusion installed and webpack configured, you can start using Diffusion in your Angular app.

Open the src/app/app.component.ts file and import the connect method and the Session interface from diffusion and the OnInit interface from @angular/core:

import { connect, Session } from 'diffusion';
import { OnInit } from '@angular/core';

and use it to create a connection to your Diffusion server:

export class AppComponent implements OnInit {
connected = false;

ngOnInit() {
connect({ host: 'localhost', port: 8080 }).then((session: Session) => {
this.connected = true;
});
}
}

The connected property can be used to show an element in the HTML component using ngIf:

<div *ngIf="connected">
<p>Connected!</p>
</div>

Run ng serve to build and serve the project at the default port of 4200, and then start a Diffusion server.

If you navigate your web browser to http://localhost:4200 you may notice that the new HTML element does not display, despite successfully getting a connection to Diffusion. This is because the Diffusion Client is not part of the Angular ‘Zone’.

Angular Zones

An important thing to remember when using Diffusion within an Angular app is how Angular handles change detection. Angular uses a feature called Zones, which patches global asynchronous operations, like setTimeout(), so that Angular can know when the operation has completed. Without this, Angular would not know when to check for state changes and update the UI. Check out this blog for more information on Angular Zones.

The Diffusion client operates outside of the Angular Zone, which means we need to tell Angular when Diffusion operations have completed in order to handle change detection correctly.

To do this, again in your app.component.ts file inject NgZone from @angular/core into your Angular component:

import { OnInit, NgZone } from '@angular/core';

export class AppComponent implements OnInit {
constructor(private zone: NgZone) {}
...
}

When an asynchronous Diffusion operation is resolved, inform the zone. We’ll use the connect method from the previous section:

connect({ host: 'localhost', port: 8080 }).then((session: Session) => {
this.zone.run(() => {
this.connected = true;
});
});

Now if you run the example, the HTML element is correctly displayed as soon as the connect operation is resolved.