What we are going to do?
In this post, we are going see how to create an hybrid mobile application using IONIC framework to manage list of to-do tasks and then publish the app in google play store.
I will break the flow into steps.
Step 1 - Create an Empty Project
Use below command to create an empty project with project name "todo".
ionic start todo blank
then navigate to todo project folder
cd todo
Add Android platform
ionic platform add android
To add iOS platform, use ios instead of android
Try checking with ionic lab to see everything is fine so far
ionic serve -l -c
You should be seeing something like this.
Step 2 - Create TODO view
Navigate to index.html in www folder.
You can see that current title is set as
<h1 class="title">Ionic Blank Starter</h1>
Change this to "TODO"
and change the ion-header-bar class to class="bar-dark" to have dark background.
Next, let us provide an option to create new task, to do that, add an input box and a button in the sub-header. Add below code snippet right above <ion-header-bar> tag.
<ion-header-bar class="bar-subheader item-input-inset">
<label class="item-input-wrapper">
<input type="text" placeholder="What you want to do?" ng-model="task.name">
</label>
<button class="button button-balanced button-small" ng-click="addTask()">
Add
</button>
</ion-header-bar>
<label class="item-input-wrapper">
<input type="text" placeholder="What you want to do?" ng-model="task.name">
</label>
<button class="button button-balanced button-small" ng-click="addTask()">
Add
</button>
</ion-header-bar>
This will add an input box and a button as an input-inset inside sub-header as shown below and clicking on this button will invoke addTask() function in controller that we will add in some time.
Next, we need to show the list of tasks in two categories, one as completed tasks and another one as incomplete tasks.
Lets add an header for each categories like below inside <ion-content> tag.
<div class="item item-divider" ng-show="tasks.incomplete.length">
Incomplete Tasks
</div>
<div class="item item-divider completedtask-divider"
ng-show="tasks.complete.length">
ng-show="tasks.complete.length">
Completed Tasks
</div>
Here, we use ng-show directive to show the headers only when there are tasks in their categories. For example, if we don't have any tasks created so far then both completed and incomplete tasks length will be zero. So that it won't show any headers.
Next, to display the list of incomplete tasks, just place the below code snippet inside <ion-content> tag and right below "Incomplete Tasks" div.
<ion-list >
<ion-item ng-repeat="task in tasks.incomplete" class="item item-checkbox item-icon-right" has-details>
<label class="checkbox" style="margin-right:42px" ng-click="toggleTaskCompleted('incomplete', task)">
<input type="checkbox" ng-checked="0">
</label>
<span ng-bind="task.name" class="item-text-wrap"></span>
<i class="icon ion-ios-close-empty" ng-click="deleteTask('incomplete',task)"></i>
</ion-item>
</ion-list>
in the same way, for completed tasks, add the below code snippet right below "Completed tasks" div.
<ion-list>
<ion-item ng-repeat="task in tasks.complete" class="item item-checkbox item-icon-right" has-details>
<label class="checkbox" style="margin-right:42px" ng-click="toggleTaskCompleted('complete', task)">
<input type="checkbox" ng-checked="1">
</label>
<strike><span ng-bind="task.name" class="item-text-wrap completedtask"></span></strike>
<i class="icon ion-ios-close-empty" ng-click="deleteTask('complete',task)"></i>
</ion-item>
</ion-list>
In both the tasks list, we have two functions,
toggleTaskCompleted - for toggling a task from completed to incomplete and vice versa.
deleteTask - for deleting a task.
We will add these two functions to the controller in sometime.
Putting all the above code snippets will look something like below.
Step 3 - Add Model and Controller
We are now done with the front end view. Let us create a new file named todo-ctrl.js inside www/js folder and define new controller named 'todoCtrl' as below.
angular.module('starter')
.controller('todoCtrl', ['$scope',
function($scope) {
}
]);
Then refer this file in index.html file just below app.js as shown below.
Then tag 'todoCtrl' controller to the body of the index.html file. So that changes made to the model in the front end will do two way binding between front end and model and button clicks will invoke corresponding function in controller. So lets do that as shown below.
<body ng-app="starter" ng-controller="todoCtrl">
Now let us create two models in controller, one for adding new task and another for storing all the tasks.
For adding new task, we get the name of the task in task model as below,
$scope.task = {
name: ""
};
For storing all the created tasks in one place, we create tasks model as,
$scope.tasks = {
'complete': [],
'incomplete': []
};
Now, let us add addTask functionality. Create a new function named addTask in the todoCtrl like below.
$scope.addTask = function(task) {
$scope.tasks.incomplete.splice(0, 0, {
'name': task.name
});
$scope.task = {};
};
what do we do here? we get the task object with the name that user enters and create a new object and then push the same in the first position of incomplete tasks array and then reset the task object, so that input field to get task name will be cleared.
Actually, we should not allow users to add empty tasks, so we will simply disable the add button if the task name is empty. We can do this in the view part itself as below.
<button class="button button-balanced button-small"
ng-disabled="!task.name.length" ng-click="addTask(task)">
As per our flow, we can add new tasks and the added tasks will be displayed under incomplete tasks. So if we add "new task1", the outcome will look like below.
The next thing that we are going to do is adding functionality for toggling tasks from complete to incomplete and vice versa. We have already added the method toggleTaskCompleted attached to check box in both complete and incomplete tasks and it takes two args - first one is to determine the task category i.e., complete or incomplete and the second one is the task itself.
Add below piece of code for this functionality.
$scope.toggleTaskCompleted = function(from, task) {
if (from == "incomplete") {
var removedTask = $scope.tasks.incomplete.splice($scope.tasks.incomplete.indexOf(task), 1);
$scope.tasks.complete.splice(0, 0, removedTask[0]);
} else {
var removedTask = $scope.tasks.complete.splice($scope.tasks.complete.indexOf(task), 1);
$scope.tasks.incomplete.splice(0, 0, removedTask[0]);
}
};
what do we do here? If the clicked task is complete, then we just remove it from complete task array and insert it in incomplete task array and vice versa.
The view would look like below when we toggle an incomplete task.
We have enclosed completed task name with <strike> tag and set the check box as checked to differentiate completed tasks from incomplete tasks.
We are almost done with the app, except deleting a task which is explained below.
We have already added a delete icon with deleteTask action, so what we have to do now is define functionality to delete a task in controller. Add below snippet for task deletion.
This function takes the task that needs to be deleted as argument.
$scope.deleteTask = function(from, task) {
if (from == "incomplete") {
$scope.tasks.incomplete.splice($scope.tasks.incomplete.indexOf(task), 1);
} else {
$scope.tasks.completed.splice($scope.tasks.completed.indexOf(task), 1);
}
};
what it does? It deletes completed task from completed tasks array and incomplete task from incomplete tasks array.
Putting all model and controller methods would be something like below.
Step 4 - Build the project
So far we have been seeing the results in browser using ionic serve. Its the time for us to build and run the project.
ionic build android
For iOS,
ionic build ios
And then run the project like below.
ionic run android
For iOS,
ionic run ios
If you don't have any real devices connected to your system while running this command, ionic will deploy it in platform specific simulator.
Cool!!! We have created the todo application. But have you noticed one important thing? If you create some tasks and come out of the app and open it again, the tasks created by you are gone. Why? What is missing here? Persistence. Yes, We have to find a way to store the tasks that we add and retrieve the stored tasks and display it in view. We will do that part in next post.
Stay tuned!
Thanks,
Jey