Rapid Prototyping with Ionic 2 and Node.js - Part 2 Last update: 2017-01-24

Rapid Prototyping with Ionic 2 and Node.js - Part 2

Ionic 2 is an awesome framework for building out your MVP with Rapid Prototyping. Not only you can benefit from the speed of the framework, you also get the advantages of Angular 2 and a cross platform app for iOS and Android in no time.

In this second part of our 3 part series we focus on building the frontend for our prototype.

All of the 3 parts of the series can be found below:

Rapid Prototyping with Ionic 2 and Node.js - Part 1: The Node.js Backend Rapid Prototyping with Ionic 2 and Node.js - Part 2: The Ionic 2 Frontend Rapid Prototyping with Ionic 2 and Node.js - Part 3: Deployment of your Components

In the first part we developed a simple REST API using Node.js to save some data in our database. It’s time to actually send those requests from an Ionic 2 app, so let’s develop our prototype and connect it in this part.

Make sure you have the server from the first series up and running to completely follow along this tutorial!

Starting a Blank Ionic 2 App

We start with a simple, blank Ionic 2 app and generate 2 providers which will help to configure our app and backend later. Start with the commands below:

ionic start devdactic-rapidfrontend blank --v2
cd devdactic-rapidfrontend
ionic g provider AppSettings
ionic g provider TodoService

As we have created new providers we need to import them into the providers array of our src/app/app.module.ts, the rest of that file stays pretty much the same:

import { AppSettings } from './../providers/app-settings';
import { TodoService } from './../providers/todo-service';
import { NgModule, ErrorHandler } from '@angular/core';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';

@NgModule({
  declarations: [
    MyApp,
    HomePage
  ],
  imports: [
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage
  ],
  providers: [TodoService, AppSettings, {provide: ErrorHandler, useClass: IonicErrorHandler}]
})
export class AppModule {}

We can now start to fill all these files with the code for our MVP Ionic 2 app and connect it to our backend.

Building the Backend Connection Provider

If you have developed an app with a backend before you know that most of the time there are multiple staging environments like development, qa, testing, live or how many instances you have.

To easily change connection between different systems, we keep the url to these systems in one file to change that url later in only on place. That’s the reason why we created the AppSettings provider.

Inside we define the apiUrl which currently points to our local Node.js server from part 1. The only function of this provider is to return this url (at the moment) so go ahead and replace your src/providers/app-settings.ts:

import { Injectable } from '@angular/core';

const CONFIG = {
  apiUrl: 'http://127.0.0.1:3001/',
};

@Injectable()
export class AppSettings {

  constructor() {
  }

  public getApiUrl() {
    return CONFIG.apiUrl;
  }
}

The second provider we generated handles all the connections and calls to the backend. Again, it’s a good idea to structure your project in a good manner and keep calls like these in a separate file from your page component which directly interacts with the view. In the first tutorial we created 3 routes:

  • Get all todos
  • Post a new todo
  • Delete a todo by it’s id

These routes are now transformed to the functions of the provider, each mapping the result to a JSON object and returning the Observable. Open your src/providers/todo-service.ts and insert:

import { AppSettings } from './app-settings';
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';

@Injectable()
export class TodoService {
  apiUrl = this.appSettings.getApiUrl();

  constructor(public http: Http, public appSettings: AppSettings) {
  }

  public getTodos() {
    return this.http.get(this.apiUrl + 'todos')
      .map(response => response.json().result);
  }

  public addTodo(newTodo) {
    return this.http.post(this.apiUrl + 'todos', {'text': newTodo})
      .map(response => response.json());
  }

  public deleteTodo(todoId) {
    return this.http.delete(this.apiUrl + 'todos/' + todoId)
      .map(response => response.json());
  }
}

Our connection to the backend is now more or less ready, we just need to use all of those beautiful functions! Let’s finish our MVP by building out the simple view for our todo list.

Creating the View for our Frontend

Inside our view we want to display a list of todos we get from the backend. Additional we need a function to create a new todo, and we also want to be able to delete a todo by its id.

Loading all the todos is just a call to our todoService and only setting our todos variable to the result which is already an observable. THe view will handle the rest of it!

To create a todo we will use the AlertController of Ionic 2 with a simple input. On save, the handler of the button will call our todoService.addTodo and subscribe to the result to update the view once it is finished.

Removing a todo is now as simple as again calling our todoService and passing the id of a todo (we will select the id in the view in the next step).

Finally we have a simply function to show a little toast message, but nothing really fancy here. Now go ahead and add everything to your src/app/pages/home/home.ts:

import { TodoService } from './../../providers/todo-service';
import { Component } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { NavController, AlertController, ToastController } from 'ionic-angular';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
  todos: Observable<any>;

  constructor(public navCtrl: NavController, public todoService: TodoService, public alertCtrl: AlertController, public toastCtrl: ToastController) {
    this.loadTodos();
  }

  loadTodos() {
    this.todos = this.todoService.getTodos();
  }

  addTodo() {
    let prompt = this.alertCtrl.create({
      title: 'Add Todo',
      message: "Enter the text for your new todo",
      inputs: [
        {
          name: 'text',
          placeholder: 'Buy Milk'
        },
      ],
      buttons: [
        {
          text: 'Cancel'
        },
        {
          text: 'Save',
          handler: data => {
            this.todoService.addTodo(data.text).subscribe(data => {
              this.showToast(data.msg);
              this.loadTodos();
            });
          }
        }
      ]
    });
    prompt.present();
  }

  removeTodo(id) {
    this.todoService.deleteTodo(id).subscribe(data => {
      this.showToast(data.msg);
      this.loadTodos();
    })
  }

  private showToast(message: string) {
    let toast = this.toastCtrl.create({
      message: message,
      duration: 3000
    });
    toast.present();
  }
}

The last missing step is to show the items inside our view.

For the todos we create a simple list which has ion-item-sliding items so we can easily add a sliding option button which will reveal the delete button.

To add a todo we use the ion-fab button which floats above our content at the desired position, which is in our case right and bottom. This component makes it super easy to add material design buttons and it looks really good out of the box!

Add all of the code below to your src/app/pages/home/home.html now:

<ion-header>
  <ion-navbar>
    <ion-title>
      Devdactic Rapid Todos
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content>
  <ion-list>
    <ion-item-sliding *ngFor="let todo of todos | async">
      <ion-item>
        {{ todo.text }}
      </ion-item>
      <ion-item-options side="right">
        <button ion-button color="danger" (click)="removeTodo(todo._id)">
        <ion-icon name="trash"></ion-icon>
        Delete
      </button>
      </ion-item-options>
    </ion-item-sliding>

  </ion-list>

  <ion-fab right bottom>
    <button ion-fab (click)="addTodo()"><ion-icon name="add"></ion-icon></button>
  </ion-fab>
</ion-content>

Now your app is ready, connected to the backend and it should show all the todos of your database. Make sure the server from the first part is up and running and have fun playing with your new MVP Ionic app with a real backend!

You can see all the steps described again in detail in the video below.

https://youtu.be/TEdsqRY8210

Conclusion

Ionic 2 with Angular 2 gives even your dummy apps or prototypes a clean code and architecture just by how the framework was designed. With only basic functions we were able to come up with a clean app that can now interact with our backend and be the starting point for future features of our MVP.

Of course you could add some more error handling, but for this version we simply hope for the best all the time.

Next time we will bring together the backend and frontend in a live environment meaning other people can actually get their hands on our MVP!