Building Real-Time Applications With Angular 2, LoopBack and FireLoop.io

Previously on How To Build A Chart Component in Angular 2 and D3 (Revised Version) I explained how to create a chart component with Angular 2 and D3, I know I promised I would create a blog for ng2d3 and I will, but first.

There is something very important I need to announce, I’m very excited to publish now that an amazing feature has been added into the LoopBack SDK Builder; its name FireLoop!!!!!

[Public Applauses and Expectation in the Background]

Presenting FireLoop.io

FireLoop is a new Real-Time Platform built on top of LoopBack that replaces the standard REST API and transforms this wonderful and mature framework into a powerful Real-Time Engine.

I want to keep this article technical and not to focus on other details, if you want to read about the motivation, comparison between other frameworks, etc. Please READ HERE

There is a newer version for this example here

Project Description

Now that you have an idea of what FireLoop is, I want to show you how to build a Real-Time Todo Application by using these technologies.

I always decide to use a Todo application when the technology is so new or important that for now the actual result application is not really significative, this will allow new developers to easily understand rather than using more complex examples.

Requirements

We are going to build a Real-Time Application using Angular 2, LoopBack and FireLoop, therefore you will need the following global packages to be installed.

1
$ npm install -g strongloop angular-cli

Create API

First we are going to create our LoopBack API and then we will install FireLoop on top to enable the Real-Time capabilities.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ mkdir todo-project && cd todo-project
$ mkdir todo-api && cd todo-api
$ slc loopback

_-----_
| | ╭──────────────────────────╮
|--(o)--| │ Let's create a LoopBack │
`---------´ │ application! │
( _´U`_ ) ╰──────────────────────────╯
/___A___\ /
| ~ |
__'.___.'__
´ ` |° ´ Y `

? What's the name of your application? todo-api

? What kind of application do you have in mind? api-server (A LoopBack API server with local User auth)
? Which version of LoopBack would you like to use? 2.x

Install FireLoop Modules

Now we need to install and configure the required modules for FireLoop to work.

1
$ npm install --save @mean-expert/{loopback-sdk-builder,loopback-component-realtime}

If you did not read the motivation just yet I need to clarify that one of the reasons I decided to bundle and brand FireLoop is because I want you to avoid all of these configurations, but until I work in a command line tool, you will need to manually do the following configurations:

But before, I can promise that when I finish the command tool; you will need to install only 1 package with zero configurations. Therefore I will be revisiting this article avoiding all of the following.

Configure Real-Time Module

Open the file server/server.js and modify the app.start method as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
app.start = function() {
// start the web server
var server = app.listen(function() {
app.emit('started', server);
var baseUrl = app.get('url').replace(/\/$/, '');
console.log('Web server listening at: %s', baseUrl);
if (app.get('loopback-component-explorer')) {
var explorerPath = app.get('loopback-component-explorer').mountPath;
console.log('Browse your REST API at %s%s', baseUrl, explorerPath);
}
});
return server;
};

Now open the file server/component-config.json and modify as follows:

1
2
3
4
5
6
7
8
{
"loopback-component-explorer": {
"mountPath": "/explorer"
},
"@mean-expert/loopback-component-realtime": {
"auth": false // For this example, we will see authentication in another post.
}
}

Configure SDK Builder

Open the file package.json and add the following within the scripts section:

1
2
3
4
5
6
7
8
9
10
{
"name": "todo-api",
"version": "1.0.0",
"main": "server/server.js",
"scripts": {
...
"build:sdk": "./node_modules/.bin/lb-sdk server/server ../todo-app/src/app/shared/sdk"
},
...
}

Ok, now we have the Back-End configurations in place, but before we move to the Angular 2 part, lets just create a simple Todo Model.

Create Todo Model

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ slc loopback:model Todo
? Enter the model name: Todo
? Select the data-source to attach Todo to: db (memory)
? Select models base class PersistedModel
? Expose Todo via the REST API? Yes
? Custom plural form (used to build REST URL): todos
? Common model or server only? common
Lets add some Todo properties now.

Enter an empty property name when done.
? Property name: text
? Property type: string
? Required? Yes
? Default value[leave blank for none]:

Create Angular 2 Application

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
$ cd ../
$ ng new todo-app
Visit http://ember-cli.com/user-guide/#watchman for more info.
installing ng2
create .editorconfig
create README.md
create src/app/app.component.css
create src/app/app.component.html
create src/app/app.component.spec.ts
create src/app/app.component.ts
create src/app/app.module.ts
create src/app/index.ts
create src/app/shared/index.ts
create src/assets/.gitkeep
create src/assets/.npmignore
create src/environments/environment.prod.ts
create src/environments/environment.ts
create src/favicon.ico
create src/index.html
create src/main.ts
create src/polyfills.ts
create src/styles.css
create src/test.ts
create src/tsconfig.json
create src/typings.d.ts
create angular-cli.json
create e2e/app.e2e-spec.ts
create e2e/app.po.ts
create e2e/tsconfig.json
create .gitignore
create karma.conf.js
create package.json
create protractor.conf.js
create tslint.json
Successfully initialized git.
Installing packages for tooling via npm.

Build FireLoop SDK

1
2
$ cd todo-api
$ npm run build:sdk

Install FireLoop SDK Dependencies

1
2
$ cd ../todo-app
$ npm install --save socket.io-client @types/socket.io-client

Open the file todo-app/src/tsconfig.json and add a new types section:

1
2
3
4
5
6
7
8
{
"compilerOptions": {
....
"types": [
"socket.io-client"
]
}
}

And to finish all of these configurations, lets just install the SDK Module within our Angular 2 Application by opening the todo-app/src/app/app.module.ts and modify as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { SDKModule } from './shared/sdk';
import { AppComponent } from './app.component';

@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
SDKModule.forRoot()
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

Disclaimer

Wow, I know that was a lot of configurations… Specially difficult if you are attracted by the final result, but you are totally new to LoopBack or even Angular 2.

This is a perfect example of why I’m creating FireLoop.io (Not just the FireLoop module but the Framework), because this is not about competing vs LoopBack; This is more about making a greater experience while working with LoopBack but also by creating a better learning curve experience, providing with a single command that setup everything. Until that happen, you now know how it is manually configured.

So… If you make it until here, I appreciate it and promise in a not so far future I’ll make everything easier in order to allow you to focus in the fun part:

Add Todo Logic

Finally, its time to have some fun!!! For so, lets modify our app.component.ts file in order to be connected with LoopBack and the FireLoop module by adding the following methods:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import { Component } from '@angular/core';
import { Todo, FireLoopRef } from './shared/sdk/models';
import { RealTime } from './shared/sdk/services';

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

export class AppComponent {

title = 'TODO Application';

private todo : Todo = new Todo();
private reference : FireLoopRef<Todo>;

constructor(private rt: RealTime) {
this.reference = this.rt.FireLoop.ref<Todo>(Todo);
}

add(): void {
this.reference.create(this.todo).subscribe(() => this.todo = new Todo());
}

update(todo: Todo): void {
this.reference.upsert(todo).subscribe();
}

remove(todo: Todo): void {
this.reference.remove(todo).subscribe();
}
}

Really simple huh? Actually I think it is really self-explanatory, but I want to talk about some details:

Models and FireLoop References are all you need

Yes!!! You read right, but… What exactly does that mean? Well… That means that now you can avoid the creation of a bunch of references for properties and methods, as we are used to.

For instance, you usually would create a private todos: Todo[] = new Array<Todo>() list, but now that is totally unnecessary.

The FireLoop Reference we created is able to be in sync with the server for any list modification and with some Angular 2 help, you will be able to directly render it as follows:

Update app.component.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<h1>
{{title}}
</h1>
<form (submit)="add()">
<input type="text" name="todo" [(ngModel)]="todo.text" placeholder="Add Todo" />
<button>Add</button>
</form>
<ul>
<li *ngFor="let todo of reference.on('changes') | async">
<input type="text" name="todo" [(ngModel)]="todo.text" />
<button (click)="update(todo)">update</button>
<button (click)="remove(todo)">remove</button>
</li>
</ul>

Again, this is a really straightforward example but I want to focus in something:

1
<li *ngFor="let todo of reference.on('changes') | async">

As you can see we are using the FireLoop reference to listen changes and by using the async pipe, Angular 2 will render all of our Todos within our application view.

But… that is not the ideal and there are several reasons that can be listed, from performance to usability.

So… What can be done?

If you have some experience with Angular 2 you may already have the assumption that the reference.on('changes') is actually returning an Observable that we can reference it and use it instead.

1
2
3
4
5
6
7
8
9
10
11
12
13
...
export class AppComponent {
...
private todo : Todo = new Todo();
private todos : Observable<Todo[]>;
private reference : FireLoopRef<Todo>;

constructor(private rt: RealTime) {
this.reference = this.rt.FireLoop.ref<Todo>(Todo);
this.todos = this.reference.on('changes');
}
...
}
1
<li *ngFor="let todo of todos | async">

This is not only better for performance, but it allows you to request what you developer or your end users actually require. What is that? Query Language.

1
2
3
4
5
6
7
8
9
10
11
12
13
...
export class AppComponent {
...
constructor(private rt: RealTime) {
this.reference = this.rt.FireLoop.ref<Todo>(Todo);
this.todos = this.reference.on('changes', {
offset: 0,
limit: 10,
order: 'id DESC'
});
}
...
}

This open a new world of possibilities because you are now in sync with the server, but you get what this specific client needs, which is awesome for real time lists, chats, reports, etc.

Again if you are new to LoopBack and you want to know what filters are available, please check the FOLLOWING INFORMATION and note that you care about the filters, but not the methods syntax, remember FireLoop is a totally new interface.

If you want to know more about FireLoop syntax please READ HERE.

Fix Angular CLI require Type

At the moment I write this article, the Angular 2 CLI Tool generates a console error, that if I don’t talk about it; it may seems this example has bugs. But, truth is the error is displayed from a vanilla installation, but how to fix it?

If you are getting a Cannot find name 'require' error, the you will need just to open the src/typings.d.ts file and add the following line:

1
declare var require: any;

That is all; you should be able to test our Real-Time Todo Application without any error in the console.

Test

If you start both, the front end/ back end servers you should be able to see the following result:

Run Server

1
2
$ cd to/todo-project/todo-api
$ node .

Run Client

1
2
$ cd to/todo-project/todo-app
$ ng serve

Open 2 browser tabs on http://127.0.0.1:4200 and have your Real-Time Todo App up and running.

TODO Real Time

What is next?

Well, there is a good amount of work ahead by building the FireLoop.io Framework, one of my priorities is to integrate with Angular 2 Universal, so… My next steps will be to deliver the last ng2d3 article and after I will be presenting improvements and new integrations so you can build even faster and better Angular 2 Applications.

If you like this series and want be aware of next releases and new packages, follow me on Twitter @johncasarrubias and if you feel it leave a comment here.

Thanks for reading.


Comments:

...