How to build Native Desktop Apps with Angular and Electron

How to build Native Desktop Apps with Angular and Electron

In this Angular and Electron tutorial, you will learn how to build native desktop apps with Angular and Electron. You might be surprised how easy it is to start building high-quality desktop apps for any platform, or even port your existing Angular app to native desktop platforms. In this tutorial I create a simple timer app, then package it for Windows, MacOS, and Linux.

In this lesson, you will learn how to build native desktop apps with Angular and Electron. You might be surprised how easy it is to start building high-quality desktop apps for any platform, or even port your existing Angular app to native desktop platforms.

This lesson covers the following topics:

  1. Configure Electron 1.7 with Angular 4.x.
  2. Build a simple timer app in Angular.
  3. Package the app for install on Windows 10, macOS, and Linux Ubuntu.

You can obtain the source code for this project on Github.

Initial Setup

Let’s kick things off by building a new angular app from scratch.

Generate the Angular App

Generate a default app with the Angular CLI.

npm install -g @angular/cli
ng new angular-electron
cd angular-electron

Update index.html

The generated root page in Angular points the base href to / - this will cause problems with Electron later on, so let’s update it now. Just add a period in front of the slash in src/index.html.

<base href="./">

Install Electron

You can install Electron in the Angular development environment.

npm install electron --save-dev
Configure Electron

The next step is to configure Electron. There are all sorts of possibilities for customization and we’re just scratching the surface.

main.js

Create a new file named main.js in the root of your project - this is the Electron NodeJS backend. This is the entry point for Electron and defines how our desktop app will react to various events performed via the desktop operating system.

The createWindow function defines the properties of the program window that the user will see. There are many more window options that faciliate additional customization, child windows, modals, etc.

Notice we are loading the window by pointing it to the index.html file in the dist/ folder. Do NOT confuse this with the index file in the src/ folder. At this point, this file does not exist, but it will be created automatically in the next step by running ng build --prod

const { app, BrowserWindow } = require('electron')

let win;

function createWindow () {
  // Create the browser window.
  win = new BrowserWindow({
    width: 600, 
    height: 600,
    backgroundColor: '#ffffff',
    icon: `file://${__dirname}/dist/assets/logo.png`
  })


  win.loadURL(`file://${__dirname}/dist/index.html`)

  //// uncomment below to open the DevTools.
  // win.webContents.openDevTools()

  // Event when the window is closed.
  win.on('closed', function () {
    win = null
  })
}

// Create window on electron intialization
app.on('ready', createWindow)

// Quit when all windows are closed.
app.on('window-all-closed', function () {

  // On macOS specific close process
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', function () {
  // macOS specific close process
  if (win === null) {
    createWindow()
  }
})

That’s it for the Electron setup, all the desktop app magic is happens under the hood.

Custom Build Command

The deployed desktop app will be an Angular AOT build - this happens by default when you run ng build --prod. It’s useful to have a command that will run an AOT production build and start Electron at the same time. This can be easily configured in the package.json file.

package.json

{
  "name": "angular-electron",
  "version": "0.0.0",
  "license": "MIT",
  "main": "main.js", // <-- update here
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e",
    "electron": "electron .", // <-- run electron 
    "electron-build": "ng build --prod && electron ." // <-- build app, then run electron 
  },
  // ...omitted
}

Run the command

You can run your angular app as an native desktop app with the following command.

npm run electron-build

At this point, you can run the command (it will take a few seconds) and it will create the dist/ folder and will automatically bring up a window on your operating system with default Angular app.

This setup does not support hot code reloads. Whenever you change some Angular code, you need to rerun the electron-build command. It is possible to setup hot reloads by pointing the window to a remote URL (such as https://localhost:4200) and running ng serve in a separate terminal.

Building the Angular App

Now we need to build an Angular App that’s worthy of being installed. I am building a single page timer that will animate a progress circle, then make a chime sound when complete.

To keep things super simple, I am writing all the code in the app.component

Install Round Progress Bar

To get the progress timer looking good quickly, I installed the angular-svg-round-progressbar package. It gives us a pre-built component that we can animate based on the current state of the timer.

npm install angular-svg-round-progressbar --save

Then add it to the app.module.ts (also add the FormsModule).

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';

import { FormsModule } from '@angular/forms'; // <-- here
import { RoundProgressModule } from 'angular-svg-round-progressbar'; // <-- here

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule, 
    FormsModule, // <-- here
    RoundProgressModule // <-- and here
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

app.component.ts

The app works by allowing the user to set the number of seconds the timer will run max. The timer progresses by running an RxJS Observable interval every 10th of a second and incrementing the current value.

I also defined several getters help deal with NaN values that can cause errors in the progress circle. They also help keep the HTML logic clean and readable.

import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/interval';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/takeWhile';
import 'rxjs/add/operator/do';


@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {

  max     = 1;
  current = 0;

  /// Start the timer
  start() {
    const interval = Observable.interval(100);
    
        interval
          .takeWhile(_ => !this.isFinished )
          .do(i => this.current += 0.1)
          .subscribe();
  }

   /// finish timer
  finish() {
    this.current = this.max;
  }

  /// reset timer
  reset() {
    this.current = 0;
  }

  /// Getters to prevent NaN errors

  get maxVal() {
    return isNaN(this.max) || this.max < 0.1 ? 0.1 : this.max;
  }

  get currentVal() {
    return isNaN(this.current) || this.current < 0 ? 0 : this.current;
  }

  get isFinished() {
    return this.currentVal >= this.maxVal;
  }

}

app.component.html

In the HTML, we can declare the progress component and display the user interface elements conditionally based on the state of the timer.

<main class="content">
        
    <h1>Electron Timer</h1>

    <div class="progress-wrapper" *ngIf="maxVal">

        <div class="text" *ngIf="!isFinished">
          {{ max - current | number: '1.1-1' }}
        </div>
        
        <div class="text" *ngIf="isFinished">
            ding!
            <audio src="assets/chime.mp3" autoplay></audio>
        </div>
        
        <round-progress
                [max]="max"
                [current]="current"
                [radius]="100"
                [stroke]="25">
        </round-progress>
        
    </div>

    <div class="controls-wrapper">
 
        <label>Seconds</label>
        <input class="input" placeholder="number of seconds" type="text" 
              [(ngModel)]="max"
              (keydown)="reset()">

            
        <button *ngIf="currentVal <= 0" (click)="start()">Start</button>
        <button *ngIf="!isFinished" (click)="finish()">Finish</button>
    </div>


</main>
Packaging for Desktop Operating Systems

Now that we have a decent app ready for desktops, we need to package and distribute it. The electron packager tool will allow to package our code into an executable for desktop platforms - including Windows (win32), MacOS (darwin), and Linux. Keep in mind, there are several other electron packaging tools that might better fit your needs.

npm install electron-packager -g
npm install electron-packager --save-dev

Linux and MacOS developers will need to install WineHQ if they plan on building desktop apps for Windows.

In this example, I am going to build an executable for Windows.

electron-packager . --platform=win32

This will generate a directory /angular-electron-win32-x64/ that contains the executable file.

And why not build one for MacOS while we’re at it.

electron-packager . --platform=darwin

This will generate a directory /angular-electron-darwin-x64/ that contains the app. Zip it and extract it on a mac system and you should be able to run it natively. You will get warnings that it’s from an unknown developer, but this is expected and it’s perfectly safe to open - it’s your own code after all.

The End

That’s it for the basic setup with Electron with Angular.

Web Development Services

Web Development Services

As one of the best Web Application Development Company, it provides a fine quality mobile app development service at an affordable price. Especially, it encourage start-ups that have unique ideas, by offering a more competitive price

HireFullStackDeveloperIndia is rated as one of the top Web Application Development Company in India by various industry magazines and review sites. They have a right blend of award-winning designers, expert programmers and Google certified digital marketers which make them a unique one-stop solution for hundreds of our clients, spread across all countries.

A Good website reflects not only your business but also it is one of the main factors why a potential customer would convert into Client. A good website design helps increase traffic driving leads to grow business. The best web design company create a custom design for each corporate website so as to help them meet their business goals.

Get Quote: https://hirefullstackdeveloperindia.com/get-a-quote/

Web Application Development Company

Web Application Development Company

Our Ecommerce Development expertise also adore clients with mobile first indexing, SEO friendly and third-party API implemented solutions that can make biz grow and succeeded in the relevant industry.

HireFullStackDeveloperIndia as a top-rated eCommerce development company, we have a great pool of dexterous a expert who have in-depth knowledge of different eminent technologies and holds multiple certifications from leading organizations.

Website: Cost of Hiring Web Application Development Company

Web Development Services in USA

Web Development Services in USA

HireFullStackDeveloperIndia goal is to get the app downloaded millions of times, generate revenue and featured on app stores.

HireFullStackDeveloperIndia is a leading Web Application Development Company in USA that mission is simple: To help our clients see what they cannot see themselves. We work alongside elite brands to uncover what we believe to be simple truths: that all roads lead to web app. That they should dream bigger. And most importantly, that they’re underestimating how an amazing mobile experience can revolutionise the way they interact with their customers.

Visit us: What is the best Full Stack Development Company in Nevada, USA?