I've been on a role when it comes to javascript andCouchbase. Over the past few weeks I've been creating content revolving around the Angular 2 framework, the JavaScript library PouchDB, and Ionic Framework for mobile. What I haven't explored yet is Couchbase in a desktop application built with Angular 2.

Two years ago I wrote about using Couchbase in a desktop application using AngularJS 1.0 and Electron , but with technology there might as well have been dinosaurs in that time period. A lot has changed and that once great post deserves a refresh.

We're going to see how to create a desktop application using Electron that is powered by Angular 2, PouchDB, Ionic 2, and Couchbase.

The Requirements

There are numerous requirements that must be met to make this project a success. They are as follows:

Node.js 4.0+ Ionic Framework 2.0 Couchbase Sync Gateway

The focus and point of this tutorial is not Ionic 2. However, Ionic 2 has a mighty fine UI layer that will save us time over alternative solutions like Bootstrap or Foundation. Ionic 2 also has Angular 2 baked in. That said, we'll need the Ionic 2 CLI installed. Node.js is a requirement because of the Node Package Manager (NPM) which we'll use to gather dependencies.

We won't be including Couchbase Server in this example, but instead Couchbase Sync Gateway and it's in-memory prototyping database. It isn't more than a single line to switch over to Couchbase Server from this example. PouchDB will communicate from our desktop application to Sync Gateway and in the other direction as well.

Configuring Couchbase Sync Gateway

Sync Gateway handles all the data orchestration and needs to be configured on a per application basis. For this particular application we're going to allow all connecting devices to be able to read and write data.

Such a configuration would look like the following:

{ "log":["CRUD+", "REST+", "Changes+", "Attach+"], "databases": { "example": { "server":"walrus:", "sync":` function (doc) { channel (doc.channels); } `, "users": { "GUEST": { "disabled": false, "admin_channels": ["*"] } } } } }

In the above sample configuration, we'll be using a database called example , but it can really be called whatever you want. The configuration should be saved to a file, for example, sync-gateway-config.json .

With Couchbase Sync Gateway downloaded and installed, the configuration can be run as follows:

/path/to/sync_gateway /path/to/sync-gateway-config.json

Sync Gateway can then be accessed from http://localhost:4985/_admin/.

Creating an Ionic 2 Project Destined for the PC

If you saw my previous guide on the topic of Couchbase with Ionic 2 and PouchDB , you're probably wondering what will be different here. The truth is, nothing really. Ionic 2 applications that don't use native Android and iOS features can be bundled into Electron applications without issue. However, some optimizations have been made to this application versus the previous.


Create a Desktop App that Syncs using Electron, PouchDB, Ionic 2 and Couchbase

In the above animation you can see a simple todo list Electron application where you can add items to the list and have them sync with Couchbase Sync Gateway and eventually other devices and Couchbase Server.

Let's start creating that simple example.

Making a Fresh Project with the Dependencies

Before we can start developing the application and packaging it in Electron, we need to create a fresh project with each of the dependencies.

From the Command Prompt or Terminal, execute the following:

ionic start ElectronExample blank --v2 cd ElectronExample

With the Ionic 2 project created we need to gather a few dependencies such as Electron and PouchDB. To do this execute the following:

npm install pouchdb --save npm install uuid @types/uuid --save npm install electron --save-dev

Because this Angular 2 application will be using TypeScript, we are best off using JavaScript libraries with type definitions. However, PouchDB doesn't have an official set of type definitions, rendering them out of date. We can get by this by including the following dependency:

npm install @types/node --save

The above dependency will give us access to the require keyword so we can import JavaScript libraries into our project.

Adding Electron for Desktop Support

With the project created we need to add Electron support. This is done by adding a special JavaScript configuration file that Electron processes at boot.

At the root of your project, create a file called electron.js with the following JavaScript code:

const electron = require('electron') const app = electron.app const BrowserWindow = electron.BrowserWindow const path = require('path') const url = require('url') let mainWindow function createWindow () { mainWindow = new BrowserWindow({width: 800, height: 600}) mainWindow.loadURL(url.format({ pathname: path.join(__dirname, 'www/index.html'), protocol: 'file:', slashes: true })) mainWindow.on('closed', function () { mainWindow = null }) } app.on('ready', createWindow) app.on('window-all-closed', function () { if (process.platform !== 'darwin') { app.quit() } }) app.on('activate', function () { if (mainWindow === null) { createWindow() } })

Most of the above code was taken directly from the Electron Starter Template , with the exception of this line:

pathname: path.join(__dirname, 'www/index.html'),

In the above line we are telling Electron which Ionic 2 page to load when the application starts. While the Electron bootstrapping is done, we need to get it bundled within our build scripts.

Open the project's package.json file and include this line:

"main": "electron.js",

The above line tells Electron which file is the configuration file. It is necessary because maybe you didn't name your file electron.js like I did. We also need to add a particular script that will build the project and launch it with Electron:

"scripts": { "ionic:build": "ionic-app-scripts build", "ionic:serve": "ionic-app-scripts serve", "electron": "ionic-app-scripts build; electron ." },

It won't package the application for deployment in an app store, but it will allow us to test it correctly with Electron on our computer.

At this point we can focus on the Angular 2 code which you may or may not have seen before.

Developing a PouchDB Provider for Angular 2

It is good practice to keep data related code separated from your page logic. In Angular 2 we can accomplish this separation through the use of a shared provider.

To create a provider in Ionic 2, execute the following from the CLI:

ionic g provider pouchdb-provider

You should end up with src/providers/pouchdb-provider.ts or similar. The name isn't really important as long as you remember what it is.

Open the provider file and include the following TypeScript:

import { Injectable, EventEmitter } from [email protected]/core'; var PouchDB = require("pouchdb"); @Injectable() export class PouchDBProvider { private isInstantiated: boolean; private database: any; private listener: EventEmitter<any> = new EventEmitter(); public constructor() { } public get(id: string) { } public put(document: any, id: string) { } public sync(remote: string) { } public getChangeListener() { } }

The provider will be injected in various pages and emit changes, hence the Injectable and EventEmitter imports. We are also importing the PouchDB JavaScript library.

The provider will act as a singleton with one database instance open for the duration that our application is open. This setup can be created in the constructor method:

public constructor() { if(!this.isInstantiated) { this.database = new PouchDB("nraboy"); this.database.changes({ live: true, include_docs: true }).on('change', change => { this.listener.emit(change); }); this.isInstantiated = true; } }

In the constructor method, if the databases isn't already instantiated we are going to instantiate it, open it, and configure the change events. For every change against the database we will emit them and eventually pick them up by subscribing to the listener.

Say we want to get a particular NoSQL document by its id. We can create a function like the following:

public get(id: string) { return this.database.get(id); }

For this particular application, the above method is more useful for our document creation method as we want to see if a document exists before we try to update it:

public put(document: any, id: string) { document._id = id; return this.get(id).then(result => { document._rev = result._rev; return this.database.put(document); }, error => { if(error.status == "404") { return this.database.put(document); } else { return new Promise((resolve, reject) => { reject(error); }); } }); }

If the document doesn't exist, it will be created instead of updated.

Because the goal here is to use Couchbase in our desktop Electron application, we need to have a sync function:

public sync(remote: string) { let remoteDatabase = new PouchDB(remote); this.database.sync(remoteDatabase, { live: true, retry: true }); }

The sync method will take our Sync Gateway hostname and database and do a two-way sync between our local database and the remote database.

public getChangeListener() { return this.listener; }

Finally we provide a way to obtain and subscribe to the change listener.

The PouchDB provider is done, but it is not ready to be used. To use it in each of our pages we need to add it to the application's @NgModule block found in the project's src/app/app.module.ts file. Open this file and include the following:

import { NgModule, ErrorHandler } from [email protected]/core'; import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular'; import { MyApp } from './app.component'; import { HomePage } from '../pages/home/home'; import { PouchDBProvider } from "../providers/pouchdb-provider"; @NgModule({ declarations: [ MyApp, HomePage ], imports: [ IonicModule.forRoot(MyApp) ], bootstrap: [IonicApp], entryComponents: [ MyApp, HomePage ], providers: [{provide: ErrorHandler, useClass: IonicErrorHandler}, PouchDBProvider] }) export class AppModule {}

Essentially we only imported the provider and added it to the providers array of the @NgModule block. Now the provider can be used in our application pages.

Adding the Page Logic for a Functional Application

This particular application only has one screen and that one screen is rather simple. Show a list of data and allow for new data to be input.

Starting with the TypeScript logic, open the project's src/pages/home/home.ts file and include the following:

import { Component, NgZone } from [email protected]/core'; import { NavController, AlertController } from 'ionic-angular'; import { PouchDBProvider } from "../../providers/pouchdb-provider"; import * as Uuid from "uuid"; @Component({ selector: 'page-home', templateUrl: 'home.html' }) export class HomePage { public items: Array<any>; public constructor(public navCtrl: NavController, public alertCtrl: AlertController, private zone: NgZone, private database: PouchDBProvider) { this.items = []; } public ionViewDidEnter() { } public insert() { } }

We've imported several Angular 2, Ionic 2, and custom components into the page and injected many of them into the constructor method. The items array will hold our synchronized data that will be displayed on the screen. The constructor method only initializes our variables.

To load data into our variables we should use the ionViewDidEnter method:

public ionViewDidEnter() { this.database.sync("http://192.168.57.1:4984/example"); this.database.getChangeListener().subscribe(data => { this.zone.run(() => { this.items.push(data.doc); }); }); }

In the ionViewDidEnter method we are starting the synchronization with our Sync Gateway and subscribing to the change events. As changes come in they will be added to the items array. We are using NgZone because change listeners are iffy in Angular 2 and we want to guarantee that the UI is updated correctly.

The insert method is pretty much all Ionic 2 logic:

public insert() { let prompt = this.alertCtrl.create({ title: 'Todo Items', message: "Add a new item to the todo list", inputs: [ { name: 'title', placeholder: 'Title' }, ], buttons: [ { text: 'Cancel', handler: data => {} }, { text: 'Save', handler: data => { if(data.title) { this.database.put({type: "list", title: data.title}, Uuid.v4()); } } } ] }); prompt.present(); }

When the method is called, a prompt will display allowing for user input. When saved, the data will be saved as a document in PouchDB and synced to Couchbase Server.

Designing the User Interface

The UI behind the TypeScript logic is short and sweet. Open the project's src/pages/home/home.html file and include the following HTML markup:

<ion-header> <ion-navbar> <ion-title> Electron w/ Couchbase </ion-title> <ion-buttons end> <button ion-button icon-only (click)="insert()"> <ion-icon name="add"></ion-icon> </button> </ion-buttons> </ion-navbar> </ion-header> <ion-content padding> <ion-list> <ion-item *ngFor="let item of items"> {{ item.title }} </ion-item> </ion-list> </ion-content>

The UI has an action bar with a button that will execute the insert method when pressed. The content of the screen is a list that displays each element from the items array as a row.

Seeing the Project in Action

There was a lot that we did in the Electron with Couchbase example. I've uploaded a working project to GitHub if you'd like to take it for a spin.

Download the project and execute the following command:

npm install

The above command restore all the project dependencies. With Sync Gateway running, execute the following to run the application with Electron:

npm run electron

Note that you'll probably have to change the Sync Gateway host in the src/pages/home/home.ts file to match your hostname.

Conclusion

You just saw how to create a desktop application that syncs withCouchbase. This application is powered by Electron , but uses Angular 2, and PouchDB. While the UI layer was Ionic 2, it didn't need to be. You could use your own UI framework like Bootstrap or similar. The goal here was more to demonstrate Electron with Couchbase and Angular 2. This guide was a step up from my previous on the topic of AngularJS 1.0 with Couchbase and Electron .

本文数据库(综合)相关术语:系统安全软件

主题: JavaJavaScriptBootstrapNode.jsAngularJSRESTGitSQLHTMLiOS
分页:12
转载请注明
本文标题:Create a Desktop App that Syncs using Electron, PouchDB, Ionic 2 and Couchbase
本站链接:http://www.codesec.net/view/522236.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 数据库(综合) | 评论(0) | 阅读(40)