Programari Lliure, WebDev

Testing Ionic 2 + NodeJS

cropped-ionic-logo-horizontal-transparentIonic: “The top open source framework for building amazing mobile apps.
Ionic is the beautiful, free and open source mobile SDK for developing native and progressive web apps with ease.”

We’ll test:

Thanks to Simon Reimler ; )

Backend: Node.js

Installing DB: Mongodb

Installing Node.js

  • Installing Node.js
  • Following this tutorial (video) <———!!!
  • Building
    • npm init
      name: (cn-node) 
      version: (1.0.0) 
      description: 
      entry point: (index.js) server.js
      test command: 
      git repository: 
      keywords: 
      author: 
      license: (ISC) GPL-3.0
    • npm install --save morgan cors express errorhandler mongoose body-parser helmet
  • If you like, you can install Atom editor: (I prefer vim 😛 )
    • wget https://atom.io/download/deb
      sudo dpkg --install atom-amd64.deb
      apm install atom-typescript
      atom &
    • previous instruccions already add: atom-typescript

Configuration files

  • Create the following files (you can copy&paste from here):
  • Database configuration:
    • # config.json 
      {
          "database": "mongodb://localhost/db"
      }
  • Component (~Page) which gives access to our entity (a todo list):
    • # todo.js
      var mongoose = require('mongoose');
      var Schema = mongoose.Schema;
       
      var TodoSchema = new Schema({
          text: {
              type: String,
              required: true
          },
          created_at: Date,
      });
       
      TodoSchema.pre('save', function (next) {
          var todo = this;
          // get the current date
          var currentDate = new Date();
       
          // if created_at doesn't exist, add to that field
          if (!todo.created_at) {
              todo.created_at = currentDate;
          }
          next();
      });
       
      module.exports = mongoose.model('Todo', TodoSchema);
  • REST API for our entity:
    • # todo-routes.js
      var express = require('express');
      
      var app = module.exports = express.Router();
      
      var Todo = require('./todo');
      
      // GET
      // Get all open Todos
      app.get('/todos', function (req, res) {
        Todo.find({}, function (err, todos) {
          if (err) {
            return res.json({ "success": false, "msg": "Error while retrieving Todo", "error": err });
          }
      
          res.status(200).send({ "success": true, "result": todos });
        });
      });
      
      // POST
      // Create a new Todo
      app.post('/todos', function (req, res) {
        if (!req.body.text) {
          return res.status(400).send({ "success": false, "msg": "You need to send the text of the todo!" });
        }
       
        var newTodo = new Todo({
          text: req.body.text
        });
       
        newTodo.save(function (err) {
          if (err) {
            console.log("some error: ", err);
            return res.json({ "success": false, "msg": "Error while creating Todo", "error": err });
          }
          res.status(201).send({ "success": true, "msg": 'Successful created new Todo.' });
        });
      });
      
      
      // DELETE
      // Remove one todo by its ID
      app.delete('/todos/:todoId', function (req, res) {
        var lectionId = req.params.todoId;
        if (!lectionId || lectionId === "") {
          return res.json({ "success": false, "msg": "You need to send the ID of the Todo", "error": err });
        }
       
        Todo.findByIdAndRemove(lectionId, function (err, removed) {
          if (err) {
            return res.json({ "success": false, "msg": "Error while deleting Todo", "error": err });
          }
          res.status(200).json({ "success": true, "msg": "Todo deleted" });
        });
      });
  • “web” Server:
    • # server.js
      var logger = require('morgan'),
       cors = require('cors'),
       http = require('http'),
       express = require('express'),
       errorhandler = require('errorhandler'),
       bodyParser = require('body-parser'),
       mongoose = require('mongoose'),
       helmet = require('helmet'),
       config = require('./config.json');
       
      var app = express();
      app.use(helmet())
       
      app.use(bodyParser.urlencoded({ extended: true }));
      app.use(bodyParser.json());
      app.use(cors());
       
      if (process.env.NODE_ENV === 'development') {
       app.use(logger('dev'));
       app.use(errorhandler())
      }
       
      var port = process.env.PORT || 3001;
       
      mongoose.Promise = global.Promise;
      mongoose.connect(config.database);
       
      app.use(require('./todo-routes'));
       
      http.createServer(app).listen(port, function (err) {
       console.log('listening in http://localhost:' + port);
      });

Serving and testing

  • Executing our defined server.js:
    • npm start
  • Browse: http://localhost:3001/todos (you’ll see the correct but empty response)
  • Use Postman to explore your REST API (you can simply use it as a Chrome App!!!)
    • Create Todos using POST
      postman-post
    • Viewing Todos using GET
      postman-get
  • Use Robomongo to explore the database:
    • wget https://download.robomongo.org/0.9.0/linux/robomongo-0.9.0-linux-x86_64-0786489.tar.gz
      tar xvzf robomongo-0.9.0-linux-x86_64-0786489.tar.gz
      cd robomongo-0.9.0-linux-x86_64-0786489/bin/
      ./robomongo
    • robomongo1

Frontend: Ionic 2

Creating the project

  • Following this tutorial 2 (video 2) <———!!!
  • Creating the project:
    • ionic start --v2 cn-ionic blank
      cd cn-ionic
      ionic g provider AppSettings
      ionic g provider TodoService
      ionic serve --browser firefox
    • Check it at: http://localhost:8100/
      • (check previous steps, since your mongodb and backend should be running)

Connecting to Backend

  • Adding API URL to AppSettings (getApiUrl method):
    • # src/providers/app-settings.ts
      import { Injectable } from '@angular/core';
      import { Http } from '@angular/http';
      import 'rxjs/add/operator/map';
      
      const CONFIG = {
       apiUrl: 'http://127.0.0.1:3001/',
      };
      
      @Injectable()
      export class AppSettings {
       constructor(public http: Http) {
         console.log('Hello AppSettings Provider');
       }
       public getApiUrl() {
         return CONFIG.apiUrl;
       }
      }
  • Mapping the result of the APIs to JSON objects:
    • # src/providers/todo-service.ts
      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());
       }
      }
  • Importing AppSettings and TodoService:
    • # src/app/app.module.ts
      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 {}

Creating a view

  • Update the home “page” to:
    • loadTodos(): loading all the todos by calling the API (todoService) and collecting the result (which is already an observable so the view can handle it).
    • addTodo():
    • # 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;
      
       loadTodos() {
       this.todos = this.todoService.getTodos();
       }
      
       constructor(public navCtrl: NavController, public todoService: TodoService, public alertCtrl: AlertController, public toastCtrl: ToastController) {
      
       this.loadTodos();
       }
      
       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();
       }
       
      }
  • Showing items in a list:
    • # src/app/pages/home/home.html
      
       
       
       My Ionic first app
       
       
      
       
      
       
       
       
       {{ todo.text }}
       
       
       
       
       Delete
       
       
       
       
       
       
       
       
       
      

Go public!

Uploading the backend to Heroku

  • Following this tutorial 3 <———!!!
  • Creating a Heroku account:
    • Access Heroku and click on “Sign-up for free”
  • Installing Heroku CLI:
    • sudo add-apt-repository "deb https://cli-assets.heroku.com/branches/stable/apt ./"
      curl -L https://cli-assets.heroku.com/apt/release.key | sudo apt-key add -
      sudo apt-get update
      sudo apt-get install heroku
  • Creating a git local repository
    • cd cn-node
      git init
      git config --global user.email "your@email"
      git config --global user.name "yourName"
      git add .
      git commit -m "First commit to test Node.JS
  • Uploading your server code to Heroku:
    • heroku login
      heroku create
      
      git push heroku master
    • You can find again your server url using:
      • heroku info -s | grep web_url | cut -d= -f2
  • Using mLab as MongoDB server:
    • Choose mLab add-on from Resources in your Personal app page:
      heroku-mlab-conf1

      • I could succesfully install it once I entered my Credit Card details, although is is a free service…
      • More doc on mLab for Heroku.
    • Configuring your server code to use this database:
      • heroku config | grep MONGODB_URI
        
        vi config.json
        {
         "database": "mongodb://heroku_..."
        }
        git add config.json 
        git commit -m "Using Heroku's mLab MongoDB"
        git push heroku master

Uploading the frontend to Ionic View

  • All commands are within cn-ionic directory.
  • Configure your frontend to use the Heroku backend:
    • # src/providers/app-settings.ts
      ...
      const CONFIG = {
       apiUrl: 'https://...herokuapp.com/',
      };
      ...
  • Create an Ionic Cloud account
    • Access Ionic Cloud and click on “Sign-up”; create your own account.
      • I had some trouble using Firefox, so finally I used Chrome.
    • ionic io init
      ionic upload
      ionic share <your@email>
    • You’ll receive an email with the link to share your new app!
  • Testing your app from a phone:
    • Install the Ionic View App in the phone
    • Open Ionic View, Log-in or Sign-up
    • If the user with the given email has been invited (using the previous “ionic share” command), he/she can review your app.
  • You can also actually upload your app to different mobile app stores.

More stuff

Using GIT

Creating remote repositories

  • You need to create your repositories for yor backend and frontend projecte.
  • Sign-up in Bitbucket and use the menu to create a repository:
    • bitbucketcreaterepo
    • After “Create repository”, choose “I have an existing project” to see the instructions/URIs

Using GIT on your frontend

Initialising GIT

  • Initialising your local repository
    • cd cn-ionic
      git init # initialising the LOCAL repository
      git config --global user.email "your@email"
      git config --global user.name "yourName"
      git add . # adding all files less those listed in .gitignore
      git commit -m "Commit before pushing to Bitbucket"
      git status # you should obtain the following two lines messsage
      master branch
      nothing to commit, working tree clean
  • Uploading your frontend to your remote repository:
    • git remote add bitbucket https://yourUser@bitbucket.org/yourUser/cn-ionic.git
      git push -u bitbucket master
      git status # you should obtain an "up-to-date" message
    • You can check the uploaded code by accessing your bitbucket repository and clicking on “Source” on the “Navigation” left panel.

Uploading updates

  • Adding any new files and/or commiting to local repository:
    • git add .
      git commit -m "Details about recent updates"
  •  Sending updates to remote repository:
    • git push

Linking a new developing machine

  • Following these tutorials:
  • If you want to work on your project from another machine, you have to (these steps are detailed later):
    • 1. to install NodeJS and Ionic 2.
    • 2. to clone the remote git repository into your machine
    • 3. to install all node modules your project uses
    • 4. to initialise your ionic local copy
  • 1. to install NodeJS and Ionic 2
    • see the top of this post.
  • 2. to clone the remote git repository into your machine
    • git clone https://yourUser@bitbucket.org/yourUser/cn-ionic.git
      cd cn-ionic
  • 3. to install all node modules your project uses
    • ionic serve # to create ionic structure
      # stop server with Ctrl+C
      npm install
    • if you get some errors, you may have a look to your package.json (where all modules are listed) and remove the initial ^ in some modules versions
  • 5. to initialise your ionic local copy
    • ionic serve # to create ionic structure
      # stop server with Ctrl+C
      ionic platform add android # your target platform
      ionic plugin add <yourPlugins> # if necessary

Retrieving updates

  • Retrieving updates from the remote repository:
    • # stop any previous running server
      git pull
      ionic serve

Using GIT on your Backend

Initialising GIT

  • Initialising your local repository
    • The local repository was previously initialised when configuring Heroku.
  • Uploading your frontend to your remote repository:
    • cd cn-node
      git remote add origin https://submariblau@bitbucket.org/submariblau/cn-nodejs.git
      git push -u origin master
      git status # you should obtain an "up-to-date" message
    • You can check the uploaded code by accessing your bitbucket repository and clicking on “Source” on the “Navigation” left panel.

Uploading updates

  • Adding any new files and/or commiting to local repository:
    • git add .
      git commit -m "Details about recent updates"
  •  Sending updates to remote repository:
    • git push

Linking a new developing machine

  • If you want to work on your project from another machine, you have to (these steps are detailed later):
    • 1. to install NodeJS.
    • 2. to clone the remote git repository into your machine
    • 3. to install all node modules your project uses
    • 4. to initialise your local copy
  • 1. to install NodeJS
    • see the top of this post.
  • 2. to clone the remote git repository into your machine
    • git clone https://yourUser@bitbucket.org/yourUser/cn-nodejs.git
      cd cn-nodejs
  • 3. to install all node modules your project uses
    • npm install
    • if you get some errors, you may have a look to your package.json (where all modules are listed) and remove the initial ^ in some modules versions
  • 5. to initialise your local copy

Retrieving updates

  • Retrieving updates from the remote repository:
    • # stop any previous running server
      git pull
      npm start

Debugging

  • Start ionic with debugging flags:
    • ionic serve -l -s -c
       [--livereload|-l] Live reload app dev files from the device (beta)
       [--consolelogs|-c] Print app console logs to Ionic CLI (livereload req.)
       [--serverlogs|-s] Print dev server logs to Ionic CLI (livereload req.)
  • https://developer.android.com/studio/command-line/adb.html

Other links

Anuncis

Deixa un comentari

Fill in your details below or click an icon to log in:

WordPress.com Logo

Esteu comentant fent servir el compte WordPress.com. Log Out / Canvia )

Twitter picture

Esteu comentant fent servir el compte Twitter. Log Out / Canvia )

Facebook photo

Esteu comentant fent servir el compte Facebook. Log Out / Canvia )

Google+ photo

Esteu comentant fent servir el compte Google+. Log Out / Canvia )

Connecting to %s