Simple ToDo list using IONIC - Part II

In the previous post we have seen how to create an hybrid mobile application using IONIC framework to manage list of to-do tasks. If you haven't read that part, please visit the post.



If you note, in the previous post, we haven't stored the tasks that we created or marked as complete. So when we close the app and reopen it again it will not shown any tasks in the view. So, in this post we will how we can store them locally and then retrieve and render them in the view.

We will make use of browser local storage to store the created tasks and we will use an angular module that gives us access to the browser local storage. that is angular-local-storage.

To have this module in our app, follow the following steps.
  • Navigate to the todo app folder in cmd prompt tool
  • Run this npm command npm install angular-local-storage
  • Copy the angular-local-storage.min.js file from todo\node_modules\angular-local-storage\dist\ folder and paste it inside todo\www\lib\ionic\js\ folder.
  • Refer angular-local-storage.min.js in index.html file below ionic.bundle.js like this
       <script src="lib/ionic/js/angular-local-storage.min.js"></script>
  • Add LocalStorageModule module in the application starter module in app.js file like this 
      angular.module('starter', ['ionic','LocalStorageModule'])


That's it. LocalStorage module is now available in our app to store and retrieve tasks in the browser's local storage.

This added LocalStorageModule has an service named localStorageService that we can use to set and get data in the local storage. and that needs to be added in controller as dependency like this.


angular.module('starter')

    .controller('todoCtrl', ['$scope', 'localStorageService',

        function($scope, localStorageService) {

Let us store the data in local storage as key-value pair and with key name as "todo_lists" as below.

var TODO_KEY = "todo_lists";


var setDataToLS = function(data){

  localStorageService.set(TODO_KEY , data);

};

var getDatafromLS = function(){
  return localStorageService.get(TODO_KEY );
};

setDataToLS function would store the data against todo_lists key in local storage.

getDatafromLS function would retrieve the data from local storage.

Next thing, let us introduce a function to load named loadToDo all complete and incomplete tasks from local storage.

var loadToDo = function(){  
  var data = getDatafromLS(); 
  if(data){
    $scope.tasks = data;
  }else{
    $scope.tasks = {'completed':[], 'incomplete':[] };
  }
};

Nothing special here. we just get the data from local storage and store it in a variable named data. In detail, if there are already some tasks then assign to data else if there are no tasks created so far lets create empty complete and incomplete arrays in an object and assign it to data variable.

This loadToDo function is the first one that needs to be called when we open the app so that it will load all tasks in the view. To do that let us call this function inside the controller as below.

loadToDo();

Next thing is we need to store the tasks whenever we create newly or update tasks from incomplete to complete and vice versa.

For that let us call setDataToLS function in addTask, deleteTask and toggleTaskCompleted function as below

$scope.addTask = function(task) {
                $scope.tasks.incomplete.splice(0, 0, {
                    'name': task.name
                });
                $scope.task = {};
                setDataToLS($scope.tasks);
            };

$scope.deleteTask = function(from, task) {
                if (from == "incomplete") {
                    $scope.tasks.incomplete.splice($scope.tasks.incomplete.indexOf(task), 1);
                } else {
                    $scope.tasks.complete.splice($scope.tasks.complete.indexOf(task), 1);
                }
                setDataToLS($scope.tasks);
            };

$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]);

                }
                setDataToLS($scope.tasks);
            };

That's it. Now all the tasks will be shown when you open the app.

To view the result in device run below command

ionic run android

I have kept the www folder of  this project in github. You can download and play around with that.

Just create an empty project and then replace the www folder with this www in github folder to get it working.

Thanks,
Jey





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>


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">
         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

What is IONIC Framework?

It is a popular front end SDK for developing hybrid mobile application with web technologies like HTML5, CSS and JS.

Why IONIC Framework?

First thing is, Write once using web technologies and generate bundle for all leading mobile platforms like Android, iOS, and Windows.

Second is, If you have to push your business into market in less time, then this is the right choice for you to go with.

and the last one is ngCordova plugins that are developed and maintained by ionic community, that you can integrate into your app in no time, to have features like App Rating, Social Sharing, Flash Light, Toast Provider, Dialogs, and much more, in your application without having to write huge lines of code. You can get more about ngCordova plugings here.

Installing IONIC Framework

Prior to installing Ionic framework, it is required to have the node package manager(npm) installed in your system since ionic framework installation is designed to happen via npm.

To get npm in your system, install Node.js from here

Once it is installed, use below command in cmd prompt to verify if npm is installed correctly.

npm --version

It should return proper npm version something like below.



Now, run the below command to get ionic and cordova (we will talk about this later) installed globally in your system.

npm install -g cordova ionic

This would take some time to install.

You can check if ionic is installed correctly by using below command.

ionic --version

It would return proper version detail like below if it was installed correctly.



I hope you have installed ionic successfully.

In the next blog, we will see how to create new project and run it  
in real device.


Thanks,
Jey

Creating New IONIC Project



Please follow previous post if you haven't already installed ionic in your system.

To create a new project use ionic start command as below.

ionic start app_name [template]

Here, the app_name is the name of the app that you want to create.

template is the piece of code to be created as a base, on top of which you want to develop the project.

A template can be ready-made templates such as blank, sidemenu, tabs - these come with ionic framework itself or any codepen or github url(explained below).

To make it clear, first let us create a project using ready-made template

ionic start sampleproject1 tabs

This command will create an ionic project based on the template given.

In the process of creating the app for us, it will ask for confirmation as to whether you want to create ionic.io account for this application. This is needed for push notification and use "Ionic view" app to view the app that we are creating now. 

Note: If you don't get it now, just ignore this part. Just press 'n' (No) for now.

Now we have our app created by ionic CLI tool for us.

The app creation flow would look something like below.


Next one is, create an app with codepen template

Codepen is a place where you can run and share your front end web work. For more, click here.

Swipable Card Nightly is one of the template that I like most in codepen. let us make a project using this template.

ionic start sampleproject2 http://codepen.io/ionic/pen/skbxh

This command also creates an app in the same way as the above one with a ready-made template.

Creating app using Github url 

Executing below command will create an ionic project using github template

ionic start sampleproject3 https://github.com/driftyco/ionic-starter-tabs

All method of creating project will have the same folder structure as shown below, except that www folder will have corresponding template code in it.




 Config.xml file

config.xml will reside in app root folder and is the main file for any ionic project you would ever create.

By default, ionic app creation tool will create an ID and Version for the app we create, something like below.

id="com.ionicframework.sampleproject1807227" 
version="0.0.1" 


We can change these values as per our need and this is the ID that will be used in google play store or apple store to identify your app. So make changes wisely.

We will discuss about the other tags of the config.xml file in another post.

Live Preview

We can see the preview of the app that we develop using serve command that ionic provides.

At first, navigate to the root folder of the app. In our example,

cd sampleproject1

and then type as below,

ionic serve -l -c

Note: This might prompt to choose an address if multiple addresses are available in your system as shown below. Just give any number.

This awesome serve tool will open our app in default browser. We can use this feature for debugging by putting break points in between.

Here optional param l - denotes lab, that is, live preview will be shown for both Android and iOS as shown below.


c - for displaying console logs in the command line tool itself.

Ionic has given an awesome feature called LiveReload, that is, whenever we make changes in the www folder, except lib, the preview will refresh automatically. cool! Isn't it?

Adding Platform to the Project

We have to add the platforms, that we want our apps to support, to the project.

For example, if we want to add support for Android platform, we can add the same like this.

ionic platform add android

for iOS,

ionic platform add ios 

Note: If you create ionic project in MAC, Ionic will add iOS platform for you by default.

You can see the added platforms under "platforms" folder in project root folder.

In the same way, we can remove platforms from the project, If we wish to, like below.

For example, to remove android platform from project.

ionic platform rm android  

Build the Project

Use below command to build projects for particular platform.

ionic build [platform]

For example, to build the project for android platform,

ionic build android

make sure that you have Java JDK installed and have set the JAVA_HOME and android SDK path in PATH environtment variable.

If build succeeded, then debug apk would have been generated in /output/apk/your_app_name.apk inside android platform folder.

For iOS,

ionic build ios

Run the Project

You can run the project using below command.

ionic run platform [options]

To run, android project,

ionic run android

Ionic will look for any real devices to deploy the package, if no devices attached, then it will deploy the package to a platform specific emulator.

Note: You can check what all are the real devices connected to the system using

adb devices

If you want to run the app in an emulator, you can use below command

ionic emulate andriod

Replace android with ios to run the project for iOS platform.

In the next post, I will share step by step guide to create a simple TO-DO list application using awesome IONIC Framework.


Thanks,
Jey