HTML5 notifications in electron apps with Angular 2

HTML5 notifications in electron apps with Angular 2

Sending information to users of your app is a common demand in modern apps. When building apps using native technologies on each platform, this task can be tedious. When using web technologies, this task becomes really easy, HTML5 is providing a unified and simple API to create notifications on all platforms.

HTML5 notifications are a great way to keep your users updated. Because Electron is using Chromium as rendering engine, those APIs are fully supported and can be used easily from within your Single Page Application.

Creating new notifications is fairly easy. You just have to create a new instance of Notification and provide some metadata.

let options = {  
    body: 'Notification Body'
};
new Notification('Notification Title', options);  

Besides title and body are some more properties that you can use to control how the notification will look like. There is also a data property that could be used to send custom data to the notification. See the full specification at https://developer.mozilla.org/de/docs/Web/API/notification.

You can also react on user's interaction with those notifications by providing a callback for onclick, onshow or onclose.

let options = {  
    body: 'Notification Body'
};
let notification = new Notification('Notification Title', options);  
notification.onclick = () => {  
    console.log('user clicked notification');
};
notification.onclose = () => {  
    console.log('notification closed');
};
// ...

So far, so good. But when using Angular 2 for example as Single Page Application framework, you may notice that interacting with bindings in those callbacks won't be recognized by Angular 2 directly.

This happens because Notification lives outside of Angular 2. In my sample repository, I want to update a instance member of a Component class once the user clicks on the notification.

public notifiy() {  
    let options = { 
        body: `Hello, this is ${this.hero.name} speaking`
    };
    let notification = new Notification('Hero Notification', options);
    notification.onclick = () => {
        this.hero.level ++;
    };
}
// ...

this.hero is bound to the template and it should automatically update the two-way binding if the user clicks on the desktop notification. To ensure Angular 2 can recognize those changes, you've to inform the underlying NgZone instance about external changes and trigger the ChangeDetection manually.

First, you've to get an instance of NgZone from the DI.

import {Component,NgZone} from [email protected]/core`;  
@Component({})
export class HeroComponent {  
  constructor(private _zone: NgZone) {
  }
}

Once you have an instance of NgZone you've to change the onclick callback to use runOutsideAngular and run offered by this._zone to tell Angular 2 that the following code runs outside of the Angular 2 Zone and notify the underlying zone again once your code is finished.

notification.onclick = () => {  
  this._zone.runOutsideAngular(() => { 
    this.hero.level ++;
    this._zone.run(()=>void 0);  
   });
};

You can grab the entire sample on github at https://github.com/ThorstenHans/electron-ts-ng2

If you haven't used Electron before, you should also double check my definitive guide on Angular 2 and Electron at https://www.xplatform.rocks/2016/02/14/angular2-and-electron-the-definitive-guide/.

Comments

comments powered by Disqus