Create a desktop Angular application with Radzen and Electron

Radzen applications are usually deployed on a web server. Sometimes it makes more sense for an application to run on the user machine. In this post I will show you how to create a desktop application from an existing Angular one via Electron.

First of all what is Electron? It is a GitHub project that enables web developers to create desktop applications with JavaScript and HTML. You are probably using an electron application right now - Visual Studio Code, Slack, Skype or Discord.

Build your application for production

The first step is to make a production build of your Radzen Angular application. The whole procedure is documented in the manual build help article.

I will use the Radzen CRM Angular sample application.

  1. Make sure you have NodeJS installed.
  2. Open a terminal/command prompt and go to the client directory of your Radzen application.
  3. Install all dependencies by running npm install.
  4. Open the src/environments/environment.prod.ts file and change all localhost references to the location of your production web server. For our example I will update environment.prod.ts like this:
    export const environment = {
     serverMethodsUrl: 'https://crm.radzen.com/',
     crm: 'https://crm.radzen.com/odata/CRM',
     securityUrl: 'https://crm.radzen.com/auth',
     production: true
    };
    
  5. Build the application.
    • Windows: .\node_modules\.bin\ng build --base-href="./" --prod
    • macOS and Linux: ./node_modules/.bin/ng build --base-href="./" --prod

That’s it! The Radzen application is now built for production (well at least the Angular part of it).

Create an Electron application

The second step is to create the Electron application.

  1. Go to the client\dist directory which contains the distribution of the Angular application created in the previous step.
  2. Create a new package.json file in the dist directory:
    {
       "name": "radzen-crm",
       "version": "1.0.0",
       "description": "",
       "main": "main.js",
       "scripts": {
         "start": "electron ."
       },
       "devDependencies": {
         "electron": "^7.1.8"
       }
    }
    
  3. Create a new minimal Electron application and save it in the dist directory as main.js:
    const {app, BrowserWindow} = require('electron');
    
    // Keep a global reference of the window object, if you don't, the window will
    // be closed automatically when the JavaScript object is garbage collected.
    let win;
    
    function createWindow() {
      // Create the browser window.
      win = new BrowserWindow({
        width: 1280,
        height: 960,
        webPreferences: {
          nodeIntegration: true
        }
      });
    
      // and load the index.html of the app.
      win.loadFile('index.html');
    
      // Emitted when the window is closed.
      win.on('closed', () => {
        // Dereference the window object, usually you would store windows
        // in an array if your app supports multi windows, this is the time
        // when you should delete the corresponding element.
        win = null;
      });
    }
    
    // This method will be called when Electron has finished
    // initialization and is ready to create browser windows.
    // Some APIs can only be used after this event occurs.
    app.on('ready', createWindow);
    
    // Quit when all windows are closed.
    app.on('window-all-closed', () => {
      // On macOS it is common for applications and their menu bar
      // to stay active until the user quits explicitly with Cmd + Q
      if (process.platform !== 'darwin') {
        app.quit();
      }
    });
    
    app.on('activate', () => {
      // On macOS it's common to re-create a window in the app when the
      // dock icon is clicked and there are no other windows open.
      if (win === null) {
        createWindow();
      }
    });
    
  4. Run npm install in the dist directory to install the Electron dependencies.
  5. Start the newly created Electron application by running npm start.

Distribute the application

Now the final part - to create distributions (installers) for macOS and Windows.

For this purpose we will use Electron Builder.

  1. Open the dist\package.json file and update it with the following content:
    {
      "name": "radzen-crm",
      "version": "1.0.0",
      "description": "",
      "main": "main.js",
      "scripts": {
        "dist:mac": "electron-builder --mac",
        "dist:win": "electron-builder --win",
        "start": "electron ."
      },
      "devDependencies": {
        "electron": "^7.1.8",
        "electron-builder": "^21.2.0"
      }
    }
    
  2. Run npm install again to instal Electron Builder.
  3. To create a windows installer run npm run dist:win. To create a macOS DMG run npm run dist:mac (you should be running on macOS though).

After Electron Builder does its business you will see the distributions in the dist directory:

  • dist\radzen-crm-1.0.0.dmg
  • dist\radzen-crm Setup 1.0.0.exe

Dealing with Angular Router

If your Radzen application uses security you will hit an issue during logout - the application screen will be empty. This can be addressed by editing the client\src\app\security.service.ts file and setting the logout method of the SecurityService class to:

logout() {
  localStorage.removeItem(TOKEN);

  this.router.navigateByUrl('/login');
}

You can add this file to Radzen’s code generation ignore list. Also rebuild the application and create new distributions.

The package.json and main.js files used in this blog post are available here.

Cheers!

by Atanas Korchev

MSGraph with Blazor

We are happy to share that Blazor applications in Radzen recently got a very important update: OData data source with AzureAD authentication!
Read more