Bài viết được dịch từ: https://scotch.io

Ionic thực sự là gì?

Ionic là một framework để xây dựng các ứng dụng di động đa nền tảng. Được xây dựng dựa trên Angular, Ionic cũng cung cấp một nền tảng để tích hợp các dịch vụ giống như đẩy các thông báo và phân tích.

Ionic không phải là một tùy chọn thay thế cho Cordova, mà nó là một thư viện UI để làm cho project Cordova trở lên tốt hơn. Ionic có thể so sánh với các framework như Bootstrap hoặc Foundation nhưng là cho Mobile không phải cho Web.

Trong bài hướng dẫn này, chúng ta sẽ tạo một ứng dụng mobile sử dụng framework Ionic và Cordova. Tôi cũng sẽ giải thích cách xây dựng các ứng dụng với PhoneGap, vì thế chúng ta không cần bận tâm tới việc cài đặt các nền tảng SDK.

Cái bạn nên biết

May mắn bạn chỉ cần hiểu cơ bản về JavaScript và framework AngularJS. Ionic được tạo ra bởi chỉ thị (directive), các thành phần (component) và sử dụng ui router cho SPA.

Hiện tại, Ionic 1.x làm việc với Angular 1.x, còn Ionic 2.x làm việc với Angular2.x.

Cài đặt và thiết lập

Cài đặt Cordova hoặc Ionic yêu cầu Node và npm đã được cài đặt trên máy của bạn. Chạy lệnh phía dưới sau khi bạn đã cài đặt Node:

npm install -g cordova ionic

Cờ -g  cài đặt cả cordova và ionic trên phạm vi toàn cục (globally) vì thế chúng ta có thể truy cập nó từ mọi nơi trên máy của mình. Nó cũng thêm chúng tới biến môi trường PATH. Để xác nhận đã cài đặt xong nhập lệnh:

ionic -v && cordova -v

Tạo một project       

Một dự án ionic có thể được tạo ra bằng cách sử dụng lệnh ionic. Nó sẽ tạo ra bộ khung các file của ứng dụng và tải các dependencies. Bạn có thể thêm các tham số để thay đổi kiểu template được tạo ra:

ionic start {appname} {template}

Đó là cú pháp để tạo tạo ra một dự án Ionic. appname là tên dự án của bạn và template là một trong những template Inonic hỗ trợ. Nó cũng có thể là một đường link github tới một custom template.

Tiếp theo chúng ta sẽ tạo một ứng dụng Todo để xem cách Ionic làm việc.

Tạo ứng dụng Todo

Mở command line trên máy của bạn và chạy lệnh:

ionic start scotch-todo blank

Chúng ta sử dụng template blank vì sự đơn giản, bạn có thể sử dụng các tempalte khác như tabs, sidemenus, ...Lệnh trên sẽ tạo ra một project mới cho chúng ta và cũng cài đặt một vài dependencies.

├── hooks          // custom cordova hooks to execute on specific commands
├── platforms      // iOS/Android specific builds will reside here
├── plugins        // where your cordova/ionic plugins will be installed
├── resources        // icon and splash screen
├── scss           // scss code, which will output to www/css/
|── www         // application - JS code and libs, CSS, images, etc.
     |---------css                 //customs styles
     |---------img               //app images
     |---------js                  //angular app and custom JS
     |---------lib                //third party libraries
     |---------index.html  //app master page        
├── bower.json     // bower dependencies
├── config.xml     // cordova configuration
├── gulpfile.js    // gulp tasks
├── ionic.project  // ionic configuration
├── package.json   // node dependencies

Cấu hình các nền tảng

Như đã thảo luận, Cordova giúp bạn viết code một lần và chạy trên nhiều nền tảng (iOS, Android, Blackberry, Window, ...) nhưng bạn có thể chỉ định rõ ràng nền tảng sẽ bao gồm trong dự án. Với ứng dụng Todo, chúng ta sẽ thử trên 2 nền tảng (iOS và Android).

cd scotch-todo
ionic platform add ios
ionic platform add android

Xem trước ứng dụng

Chúng ta có thể xem trước ứng dụng của mình trong trình duyệt sử dụng Ionic. Điều này không được khuyến khích nhưng có thể sử dụng để xem trước ứng dụng Todo.

Để xem ứng dụng, chạy lệnh sau trong thư mục scotch-todo:

ionic serve

Lệnh trên sẽ mở một trình duyệt tại địa chỉ http:localhost:8100. Bạn có thể thấy trình duyệt quá lớn để xem một ứng dụng mobile và vì vậy, Ionic thêm --lab như một tùy chọn để chạy ứng dụng trong trình duyệt bạn sẽ xem trước ứng dụng giống như trong Android và iOS.

ionic serve --lab

Xây dựng một thứ gì đó

Ionic về cơ bản là một ứng dụng web SPA , chúng ta cần một file index.html mặc dù không cần các route vì ứng dụng Todo chỉ có một view.

Đầu tiên chúng ta cập nhật các file www/index.htmlwww/js/app.js:

www/index.html

<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
    <title></title>

    <link href="lib/ionic/css/ionic.css" rel="stylesheet">
    <link href="css/style.css" rel="stylesheet">
    <!-- ionic/angularjs js -->
    <script src="lib/ionic/js/ionic.bundle.js"></script>

    <!-- cordova script (this will be a 404 during development) -->
    <script src="cordova.js"></script>

    <!-- your app's js -->
    <script src="js/app.js"></script>
  </head>
  <!-- your app's js -->
  <body ng-app="scotch-todo">

    <ion-pane>
     <ion-header-bar class="bar-dark">
        <h1 class="title">Scotch-Todo</h1>
      </ion-header-bar>
      <ion-content>
      </ion-content>
    </ion-pane>
  </body>
</html>

www/js/app.js

//setup angular
var app = angular.module('scotch-todo', ['ionic']);

Ionic yêu cầu các dependencies (angular-ui-router, angular-animate, angular-sanitize, ...) tất cả được gộp vào một file là ionic.bundle.js.

Đó là các file chúng ta sẽ làm việc trong bài hướng dẫn này. Trước khi tiếp tục, chúng ta hãy xác định các task cần hoàn thành để không bị mất tập trung:

  • Thiết lập dịch vụ Local Storage để lưu trữ dữ liệu
  • Tạo một main controller để tương tác với view
  • Cập nhật file index.html để làm việc với controller

Dịch vụ Local Storage

HTML5 là người bạn thân thiết của ionic với nhiều tùy chọn lưu trữ. Local Storage là một trong số đó và nó phù hợp với ứng dụng của chúng ta bởi vì nó cung cấp tất cả các tùy chọn, nó có khả năng lưu trữ dữ liệu ngay cả khi trình duyệt hoặc ứng dụng đã đóng.

Angular có một dịch vụ (service) sử dụng các API của Local Storage và có sẵn trên GitHub là angular-local-storage. Ionic sử dụng bower để quản lý các dependencies, để cài đặt đặt angula-local-storage sử dụng lệnh sau:

bower install angular-local-storage --save

Lệnh trên sẽ tải và thêm angular-local-storage tới ứng dụng của chúng ta. Ngay bên dưới ionic.bundle.js:

<script src="lib/angular-local-storage/dist/angular-local-storage.js"></script>

Tiếp theo chúng ta tiêm các dependency vào ứng dụng của mình:

var app = angular.module('scotch-todo', ['ionic', 'LocalStorageModule']);

Để tránh bị nghi đè trong tương lai, chúng ta cần thêm tiền tố cho toàn bộ dữ liệu được lưu trữ bởi Local Storage:

app.config(function (localStorageServiceProvider) {
    localStorageServiceProvider
    .setPrefix('scotch-todo');
});

Hãy di chuyển tới nhiệm vụ thứ 2 của chúng ta.

Main controller

Controller sẽ đứng giữa dữ liệu của chúng ta (Local Storage) và view (www/index.html). Trước tiên hãy tạo cấu trúc của controller như ở bên dưới trong file www/js/app.js

app.controller('main', function ($scope, $ionicModal, localStorageService) { //store the entities name in a variable var taskData = 'task';

  //initialize the tasks scope with empty array
  $scope.tasks = [];

  //initialize the task scope with empty object
  $scope.task = {};

  //configure the ionic modal before use
  $ionicModal.fromTemplateUrl('new-task-modal.html', {
    scope: $scope,
    animation: 'slide-in-up'
  }).then(function (modal) {
    $scope.newTaskModal = modal;
  });

  $scope.getTasks = function () {
    //fetches task from local storage
    ...
  }
  $scope.createTask = function () {
    //creates a new task
    ...
  }
  $scope.removeTask = function () {
    //removes a task
    ...
  }
  $scope.completeTask = function () {
    //updates a task as completed
    ...
  }
})

Chú ý chúng ta đã tiêm localStorageService vào controller vì thế chúng ta có thể tương tác với Local Storage từ controller. Chúng ta cũng tiêm dịch vụ (service) $ionicModal để giúp tạo ra các nhiệm vụ từ modal.

Chúng ta cũng cần khai báo controller trong view. Cập nhật thẻ <body> trong file index.html như dưới đây:

<body ng-app="scotch-todo" ng-controller="main" ng-init="getTasks()">
... 
</body>

Chúng ta đã tạo ra một tiến trình hợp lý. Giờ hãy hoàn thành các phương thức trong controller. Hãy bắt đầu với getTasks() phương thức này sẽ kiểm tra tasks trong Local Storage và nếu tồn tại, sẽ gán nó vào biến $scope.tasks:

$scope.getTasks = function () {
          //fetches task from local storage
          if (localStorageService.get(taskData)) {
              $scope.tasks = localStorageService.get(taskData);
          } else {
              $scope.tasks = [];
          }
   }

Chúng ta có thể tạo một task mới bằng cách thêm một đối tượng task vào mảng tasks và cập nhật Local Storage:

$scope.createTask = function () {
          //creates a new task
          $scope.tasks.push($scope.task);
          localStorageService.set(taskData, $scope.tasks);
          $scope.task = {};
          //close new task modal
          $scope.newTaskModal.hide();
   }

Để xóa task chúng ta có thể xóa đối tượng task từ mảng tasks và cập nhật Local Storage.

$scope.removeTask = function (index) {
          //removes a task
          $scope.tasks.splice(index, 1);
          localStorageService.set(taskData, $scope.tasks);
     }

Khi hoàn thành một task chúng ta có thể tìm task đó trong mảng tasks sử dụng index của nó,cập nhật giá trị compledted và cập nhật Local Storage.

$scope.completeTask = function (index) { 
 //updates a task as completed 
 if (index !== -1) {
  $scope.tasks[index].completed = true; 
 } 

  localStorageService.set(taskData, $scope.tasks); 
}

Chúng ta đã hoàn thành controller. Tiếp theo là view.

View

Chúng ta sử dụng thành phần card của ionic để hiển thị các task. Ngay bên trong thẻ <ion-content> thêm đoạn code sau:

<div class="list card" ng-repeat="task in tasks track by $index">
            <div class="item item-divider">
                <span ng-bind="task.title"></span>
            </div>
            <div class="item item-body">
                <strong>Title: <span ng-bind="task.title"></span></strong>
                <p>
                    <span ng-bind="task.content"></span>
                </p>
            </div>

            <div class="item tabs tabs-secondary tabs-icon-left">
                <span class="item item-checkbox">
                    <label class="checkbox">
                        <input type="checkbox" ng-model="task.completed" ng-click="completeTask($index)">
                    </label>
                </span>
                <a class="tab-item assertive" ng-click="removeTask($index)">
                    <i class="icon ion-android-close"></i>
                </a>
            </div>

</div>

Chúng ta đã có một danh sách các tasks. Bây giờ là tạo một task mới, chúng ta sẽ sử dụng modal cái đã được cấu hình trong controller. Ngay trước thẻ đóng <body> thêm đoạn code này:

<script id="new-task-modal.html" type="text/ng-template">
        <ion-modal-view>
            <ion-header-bar class="bar-dark">
                <h1 class="title">Create a new Task</h1>
                <button class="button button-icon" ng-click="closeTaskModal()">
                    <i class="icon ion-android-close"></i>
                </button>
            </ion-header-bar>
            <ion-content>
                <form ng-submit="createTask()">
                    <div class="list list-inset">
                        <label class="item item-input">
                            <input ng-model="task.title" type="text" placeholder="Task title">
                        </label>
                        <label class="item item-input">
                            <textarea ng-model="task.content" rows="5" placeholder="Task content"></textarea>
                        </label>
                        <ul class="list">
                            <li class="item item-toggle">
                                Completed?
                                <label class="toggle toggle-balanced">
                                    <input type="checkbox" ng-model="task.completed">
                                   <div class="track">
                                        <div class="handle"></div>
                                    </div>
                                </label>
                            </li>
                        </ul>
                        <button type="submit" class="button button-block button-positive">Create Task</button>
                    </div>
                </form>
            </ion-content>
        </ion-modal-view>
    </script>

Cuối cùng thêm một nút tới chỉ thị (directive) ion-header-bar cái sẽ được sử dụng để mở modal.

<ion-header-bar class="bar-dark">
    <h1 class="title">Scotch-Todo</h1>
    <!-- New Task button-->
    <button class="button button-icon" ng-click="openTaskModal()">
        <i class="icon ion-compose"></i>
    </button>
</ion-header-bar>

Chúng ta đã hoàn thành ứng dụng Todo list. Đến đây, tôi không nghĩ chúng ta cảm thấy hài lòng khi kiểm thử một ứng dụng dành cho di động trên trình duyệt. Hãy làm một vài thứ để giải quyết nó.

Kiểm thử với ứng dụng PhoneGap

PhoneGap là một framework mã nguồn mở miễn phí nó cho phép bạn tạo ra ứng dụng di động sử dụng các API web đã được chuẩn hóa cho các nền tảng (di động) mà bạn quan tâm.

Chúng ta chỉ sử dụng PhoneGap để bổ sung cho những nhược điểm của Cordova.

Một trong những nhược điểm của Codova là kiểm thử theo thời gian thực. Với Cordova chúng ta chỉ có thể cài đặt các SDK, xây dựng ứng dụng và kiểm thử với các SDK, nó có thể chậm và ảnh hưởng tới hiệu suất.

Ứng dụng PhoneGap giúp chúng ta kiểm thử ứng dụng của mình theo thời gian thực trong khi đang xây dựng nó. Không cần biên dịch hoặc xây dựng trước khi kiểm thử. Tất cả cái chúng ta cần làm là đặt máy tính và các thiết bị di động của mình trên cùng một mạng. Hãy chạy lệnh sau để cài đặt PhoneGap:

npm install -g phonegap

Tiếp theo chúng ta cần cài đặt ứng dụng cho thiết bị di động của mình. Tôi có một điện thoại Android vì vậy tôi tải từ Play Store. Bạn có thể tìm kiếm các nền tảng khác tại PhoneGap App website.

Cuối cùng, thay vì sử dụng ionic serve trong thư mục Todo App, chúng sử dụng lệnh sau:

phonegap serve

Chú ý địa chỉ IP bởi vì đó là cái chúng ta sẽ sử dụng để nói chuyện với thiết bị mobile của mình.

Mở ứng dụng PhoneGap đã được cài đặt trên thiết bị của bạn và thay thế địa chỉ IP và cổng với địa chỉ IP và cổng ở phía trên sau khi chạy lệnh phonegap serve và nhấn kết nối. Và đây là kết quả:

Đến đây chúng ta đã hoàn thành ứng dụng Todo. Tiến hành chạy và kiểm thử trên điện thoại di động của mình.

Kết luận

Tôi rất vui mừng và tự hào vì đã hoàn thành bài hướng dẫn này cùng với các bạn. Như bạn có thể thấy, bạn không cần phải biết Java, Objective C hoặc C# để phát triển một ứng dụng di động, chúng ta chỉ cần áp dụng các kỹ năng phát triển Web của mình. Tôi nghĩ điều đó thật tuyệt vời. Đây mới chỉ là bắt đầu, hy vọng bạn sẽ tìm thấy nhiều hơn về Ionic trên Scotch.