Todo-JS - Part I - Getting Started

1.1. Create an application on Built.io Backend

Creating an application on Built.io Backend is like deploying your app on the server. You do not have to maintain separate databases, servers or load balancers for your app. Built.io backend does it for you. Let’s create an application on Built.io Backend as shown below:

1 Create New app.gif

An application in Built.io Backend contains all the data that is associated with your mobile/web app. Through this application, you will be able to handle everything related to your mobile app, including users, events, devices, push notifications, and so on.

Note down the API key generated while creating the application. It will be later used to link your application with the Built.io Backend JavaScript SDK.

1.2. Classes and objects

When you define a class for your app, you actually define the blueprint of the data. A class is like your app’s data structure/table, and the objects are the records within the table. We have covered Classes and Objects in detail in our docs. It is recommended that you read the whole section and get a thorough understanding of these concepts before moving forward.

In our sample To-Do app, we will create only one class: Tasks. When your app users add new tasks in this To-Do app, these individual tasks will be saved as objects in the Tasks class.

While creating a new class, we would need to define three things:

  1. Class name: Enter class name as 'Tasks'
  2. Fields: Create two fields within the class: Task Text and Task Status, with datatype as Text and Boolean, respectively.
  3. Permissions: As of now, we will give create, read, update, and delete access to all the to-do items to everyone. User permissions (or ACL) are defined in detail in Part III of this tutorial.

Let us create 'Tasks' class in Built.io Backend as shown below:

Class.gif

1.3. Directory structure

You folder structure should look like this.

folder-structure.png

As of now, the app.js, style.css, and index.html files would be blank. We will enter the required code in these files as we move forward.

1.4. Loading libraries / files in index.html

<!DOCTYPE html>
<html lang="en" ng-app="todoApp">
<head>
    <meta charset="UTF-8">
    <title>Todo</title>
    <script type="text/javascript" src="js/built_rt.min.js"></script>
    <script type="text/javascript" src="js/angular.min.js"></script>
    <script type="text/javascript" src="js/app.js"></script>
    <link rel="stylesheet" href="css/style.css">

It is important to follow the same sequence of the included JS files as mentioned in the above code.

We have loaded the Built.io Backend JavaScript SDK (js/built.min.js) first, followed by Angular.JS framework (js/angular.min.js), and then our application file. This is to ensure that the SDK loads first and then Angular. The remaining HTML structure simply creates an input text field and an 'add' button.

1.5. Integrating JavaScript SDK

To initialize the SDK, open app.js, and add the following code in the beginning. 

var BuiltApp = Built.App('application_api_key')

1.6. Managing tasks

//TODO-APP
angular.module('todoApp',[])
  .controller('TaskListController', function($scope) {
    $scope.taskList = [];
   ...
   })
// Safely apply changes-
 function $sa(scope, fn) {
  (scope.$$phase || scope.$root.$$phase) ? fn() : scope.$apply(fn);
 }

In the app.js file, we first introduce an angular module angular.module('todoApp', []) that enables us to define things like controllers. We also define an array $scope.taskList = [] to hold all tasks.

/*
Populate `taskList`
===================
Fetch data from Built.io Backend
*/
// `BuiltClass` is an instance of Backend class.
var BuiltClass = BuiltApp.Class('tasks');
// `builtQuery` is an instance of Backend's Query.
var builtQuery = BuiltClass.Query();
// Execute builtQuery
builtQuery.exec()
 .then(function(objects){
   $sa($scope, function(){
     $scope.taskList = objects
   });
 });

The above code snippet is part of 'TaskListController'. When the app first launches, you want it to display all the existing objects of the 'Tasks' class. To do this, we first create an instance of Built.io Backend class using the uid (tasks). We have also added a Built.io Backend Query instance 'builtQuery', which is used to create and execute various queries. But, as of now, we will only execute a query to fetch objects. You can read more about Query here.

We then execute 'builtQuery' with exec() method as shown in the code snippet. On success, we will get an array of objects fetched from the Tasks class in Built.io Backend. We will then assign those objects to $scope.taskList.

Now that the angular module and controller are defined in app.js, let us include these in our HTML file.

We will also add ng-submit=”addTask()” in the form tag of our HTML code. This will ensure that when a user submits a form, the 'addTask' method within the controller in our app.js file will be triggered.

<div ng-controller="TaskListController">
<!-- Form to create new task -->
<form ng-submit="addTask()">
  <input type="text" ng-model="taskText" size="30" placeholder="add new todo here">
  <input class="btn-primary" type="submit" value="add">
</form>

Now, let’s have a look at the controller methods that we had defined in our app.js code structure.

Add new task

The addTask method will be called when you click on the 'add' button in our To Do App. 

We first create a 'Task' constructor var Task = BuiltApp.Class('tasks').Object; that returns an object constructor.

$scope.addTask = function(){
  /* 
    Save task object to Built.io Backend
  */
  var Task = BuiltApp.Class('tasks').Object;
  // `newTask` is Object of `Task` constructor
  var newTask = Task({
    task_text   : $scope.taskText,
    task_status : false
  })
  // `newTask` save method create new Object in Built.IO Backend's `tasks` Class
  newTask.save()
}

The above code will be used to create a 'newTask' object in 'tasks' class in Built.io Backend from 'Task' constructor. Initially, the 'done' property has 'False' as default value, as we want the new task to remain 'uncompleted' when created.

The newTask.save() method saves the 'newTask' Object on Built.io Backend. 

The save function returns a promise with a then method. This then method will accept a function which will give a 'responseObj' as an argument. Then we can add 'responseObj' to our $scope.taskList.

.then(function(responseObj){
  // On success `responseObj` return a Built.IO Backend's Object we just created
  $sa($scope, function(){
    // add `responseObj` to our `$scope.taskList`
    $scope.taskList.push(responseObj);
    // clear the input text on html form
    $scope.taskText = '';
  })
})

Now that we have learned how to add new tasks, let us understand how to display these tasks in our app through HTML. To do this, we will add a list area in our HTML code as shown below.

<!-- Task list -->
<ul class="unstyled">
  <li ng-repeat="task in taskList">
    <input type="checkbox" ng-model="task.toJSON().task_status" ng-click="editTaskStatus(task)">
    <span class="done-{{task.toJSON().task_status}}">{{task.toJSON().task_text}}</span>
    <span class="action" ng-click="removeTask(task)">delete</span>
    <span class="action" ng-click="editTaskText(task)">edit</span>
  </li>
</ul>

Whenever the '$scope.taskList' array would be updated, the changes would reflect in our HTML. We have also introduced ng-repeat in the code that would repeat HTML elements. For each task, we have created a checkbox and three <span/> elements: hold todo text, delete task, and edit task. ng-click   is used to call a particular method defined in the controller.

Go ahead and run the html file in your browser. Add a task and you should see something like:

simple-todo-1.png

Update task status

Now let’s add editTaskStatus method in our 'TaskListController'. This method will be used to mark a particular task as done.

/* Edit task status */
$scope.editTaskStatus = function(task){
  var index   = $scope.taskList.indexOf(task);
  var newTask = task.set('task_status',task.get('task_status'));
  $scope.updateTask(newTask, index);
}

Here var index will hold the index of the current task item in the taskList. We have used the .set method from the SDK that returns the updated object, and assigns it to the 'newTask' variable. It is important to note that this method will not save 'newTask' object on Built.io Backend. To save it on Built.io Backend, we will use the updateTask method.

Update task

/* Update task */
$scope.updateTask = function(newTask, index) {
  //Save updated `task` to Built.IO Backend
  newTask.save()
    .then(function(data) {
      $sa($scope, function() {
        $scope.taskList.splice(index, 1, data);
      })
    });
}

The 'updateTask' method updates the task on Built.io Backend. This method accepts two arguments: newTask and index. The newTask.save() method will save the object to Built.io Backend. To reflect this change in our code, we will use:

$scope.taskList.splice(index,1,data);

Edit task text

Similarly we can update text of our task using 'editTaskText'.

/* Edit task text */
$scope.editTaskText = function(task) {
  var index = $scope.taskList.indexOf(task);
  var text = prompt("Task Text", task.get('task_text'));
  var newTask = text && task.set('task_text', text);
  if (newTask) {
    $scope.updateTask(newTask, index);
  }
}

The above code allows the user to edit the task text in a new prompt box.

Delete task

Now let’s understand how to delete a task from a taskList. Whenever the user clicks the 'delete' link of any task from a list, the 'removeTask' method from the 'TaskListController' is called.

/* Delete task from taskList */
$scope.removeTask = function(task) {
  //Get index number of todo
  var index = $scope.taskList.indexOf(task);
  //Delete from Built.IO Backend
  task.delete()
    .then(function(data) {
      $sa($scope, function() {
        $scope.taskList.splice(index, 1);
      })
    });
}

The task.delete() is a method from JavaScript SDK, which deletes the task object from Built.io Backend. It returns a promise, and on success, the specified object is removed from $scope.taskList.

PREVNEXT: Part II - User Authentication