[Ionic 初心者筆記] 官方教學 - Ch 5 擴展你 App 的功能
本文章參考 Ionic 官方教學,希望讓初學者對於如何用 Ionic Framework 開發跨平台的 HTML5 mobile apps 有初步的概念。Chapter 1: All About Ionic
Chapter 2: Installation
Chapter 3: Starting your app
Chapter 4: Testing your app
Chapter 5: Building out your app
Chapter 6: Publishing your app
Chapter 5: Building out your app
現在我們已經知道如何測試自己的 App,這一章我們將進一步完善我們的功能。由於 Ionic 搭配的是 Angular,所以熟悉基本的 Angular 觀念是必須的,若讀者對於 Angular 還不熟悉的話可以參考筆者之前寫的文章。
<!-- Center content -->
<ion-side-menu-content>
<ion-header-bar class="bar-dark">
<h1 class="title">Todo</h1>
</ion-header-bar>
<ion-content>
<!-- our list and list items -->
<ion-list>
<ion-item ng-repeat="task in tasks">
{{task.title}}
</ion-item>
</ion-list>
</ion-content>
</ion-side-menu-content>
此刻我們移動到 app.js 並在裡頭加入 Angular 引入的 module 和定義的 controller。並把 todos 透過 $scope 和 model binding 起來,這樣我們就可以看到 Todolist 的內容了!
angular.module('todo', ['ionic'])
.controller('TodoCtrl', function($scope) {
$scope.tasks = [
{ title: 'Collect coins' },
{ title: 'Eat mushrooms' },
{ title: 'Get high enough to grab the flag' },
{ title: 'Find the Princess' }
];
});
若正常的話使用測試方法,你將看到上圖所顯示的畫面。
一、創見任務(todos)
上面示範的只是人工塞的假資料,但我們希望設計使用者在點擊新增任務時,會跳出一個 modal box,讓使用者可以新增任務。為了建立這樣的功能,我們使用 Angular 中的 template(可以從本地端或是遠端載入的元件模版),此處我們把 template 加在 </ion-side-menu> 之後,當使用者點擊新增任務時就會跳出 modal box 可以輸入資料。當我們點選創見任務的按鈕時會呼叫 createTask(task) 這個 controller,並把創見的任務物件傳遞過去。在 input 的部份則透過 data-modal-binding 的方式綁定 ng-model="task.title",使用者所送出的資料則會存到 $scope.tasks.title 並放入 $scope.tasks 陣列裡。
<script id="new-task.html" type="text/ng-template">
<div class="modal">
<!-- Modal header bar -->
<ion-header-bar class="bar-secondary">
<h1 class="title">New Task</h1>
<button class="button button-clear button-positive" ng-click="closeNewTask()">Cancel</button>
</ion-header-bar>
<!-- Modal content area -->
<ion-content>
<form ng-submit="createTask(task)">
<div class="list">
<label class="item item-input">
<input type="text" placeholder="What do you need to do?" ng-model="task.title">
</label>
</div>
<div class="padding">
<button type="submit" class="button button-block button-positive">Create Task</button>
</div>
</form>
</ion-content>
</div>
</script>
接下來我們開始撰寫 TodoCtrl 邏輯的部份,我們先注入 ionicModal (依賴注入)讓我們可以之後可以使用 modal box,並設定 modal 的介面是從上面設計的 template 產生。而 modal 的顯示與隱藏則用 hide / show 去操作。
angular.module('todo', ['ionic'])
.controller('TodoCtrl', function($scope, $ionicModal) {
// No need for testing data anymore
$scope.tasks = [];
// Create and load the Modal
$ionicModal.fromTemplateUrl('new-task.html', function(modal) {
$scope.taskModal = modal;
}, {
scope: $scope,
animation: 'slide-in-up'
});
// Called when the form is submitted
$scope.createTask = function(task) {
$scope.tasks.push({
title: task.title
});
$scope.taskModal.hide();
task.title = "";
};
// Open our new task modal
$scope.newTask = function() {
$scope.taskModal.show();
};
// Close the new task modal
$scope.closeNewTask = function() {
$scope.taskModal.hide();
};
});
二、新增專案
現在我們重新擴展我們的 App 功能,讓我們可以在 Project 新增 todos ,並用 localstorage 來儲存新增的資料。
新的主要內容的 mockup
{% raw %}
<!-- Center content -->
<ion-side-menu-content>
<ion-header-bar class="bar-dark">
<button class="button button-icon" ng-click="toggleProjects()">
<i class="icon ion-navicon"></i>
</button>
<h1 class="title">{{activeProject.title}}</h1>
<!-- New Task button-->
<button class="button button-icon" ng-click="newTask()">
<i class="icon ion-compose"></i>
</button>
</ion-header-bar>
<ion-content scroll="false">
<ion-list>
<ion-item ng-repeat="task in activeProject.tasks">
{{task.title}}
</ion-item>
</ion-list>
</ion-content>
</ion-side-menu-content>
左側欄:
<ion-side-menu side="left">
<ion-header-bar class="bar-dark">
<h1 class="title">Projects</h1>
<button class="button button-icon ion-plus" ng-click="newProject()">
</button>
</ion-header-bar>
<ion-content scroll="false">
<ion-list>
<ion-item ng-repeat="project in projects" ng-click="selectProject(project, $index)" ng-class="{active: activeProject == project}">
{{project.title}}
</ion-item>
</ion-list>
</ion-content>
</ion-side-menu>
現在我們重新擴展我們的 App 功能,讓我們可以在 Project 新增 todos ,並用 localstorage 來儲存新增的資料。
angular.module('todo', ['ionic'])
/**
* The Projects factory handles saving and loading projects
* from local storage, and also lets us save and load the
* last active project index.
*/
.factory('Projects', function() {
return {
all: function() {
var projectString = window.localStorage['projects'];
if(projectString) {
return angular.fromJson(projectString);
}
return [];
},
save: function(projects) {
window.localStorage['projects'] = angular.toJson(projects);
},
newProject: function(projectTitle) {
// Add a new project
return {
title: projectTitle,
tasks: []
};
},
getLastActiveIndex: function() {
return parseInt(window.localStorage['lastActiveProject']) || 0;
},
setLastActiveIndex: function(index) {
window.localStorage['lastActiveProject'] = index;
}
}
})
.controller('TodoCtrl', function($scope, $timeout, $ionicModal, Projects, $ionicSideMenuDelegate) {
// A utility function for creating a new project
// with the given projectTitle
var createProject = function(projectTitle) {
var newProject = Projects.newProject(projectTitle);
$scope.projects.push(newProject);
Projects.save($scope.projects);
$scope.selectProject(newProject, $scope.projects.length-1);
}
// Load or initialize projects
$scope.projects = Projects.all();
// Grab the last active, or the first project
$scope.activeProject = $scope.projects[Projects.getLastActiveIndex()];
// Called to create a new project
$scope.newProject = function() {
var projectTitle = prompt('Project name');
if(projectTitle) {
createProject(projectTitle);
}
};
// Called to select the given project
$scope.selectProject = function(project, index) {
$scope.activeProject = project;
Projects.setLastActiveIndex(index);
$ionicSideMenuDelegate.toggleLeft(false);
};
// Create our modal
$ionicModal.fromTemplateUrl('new-task.html', function(modal) {
$scope.taskModal = modal;
}, {
scope: $scope
});
$scope.createTask = function(task) {
if(!$scope.activeProject || !task) {
return;
}
$scope.activeProject.tasks.push({
title: task.title
});
$scope.taskModal.hide();
// Inefficient, but save all the projects
Projects.save($scope.projects);
task.title = "";
};
$scope.newTask = function() {
$scope.taskModal.show();
};
$scope.closeNewTask = function() {
$scope.taskModal.hide();
}
$scope.toggleProjects = function() {
$ionicSideMenuDelegate.toggleLeft();
};
// Try to create the first project, make sure to defer
// this by using $timeout so everything is initialized
// properly
$timeout(function() {
if($scope.projects.length == 0) {
while(true) {
var projectTitle = prompt('Your first project title:');
if(projectTitle) {
createProject(projectTitle);
break;
}
}
}
});
});
老實說這章是這一系列教程中最難的部份,不過只要多加練習相信大家一定能突破難關。現在,我們終於有個完成的 TodoList App 了!下一章也是最後一章,我們將練習如何將你的 App 上架到市集,讓把拔、馬麻,爺爺奶奶甚至隔壁班的心儀女生都能使用你所寫的 App 啦!
參考文件:
1. The Ionic Book
2. ionic book 簡中