AngularJS

AngularJS To Do List App

AngularJS is a great framework that frees you from much of the tedious and error-prone code for DOM updating. We've provided an example app running on DreamFactory for the backend using AngularJS and Twitter Bootstrap. This app is very basic. We have a more advanced AngularJS example that you can find on GitHub. That one uses Bower, Grunt, and our SDK.

The app of choice here is the infamous to do list. To try it out for yourself, just sign up for a free DreamFactory account. You can add items to the list, toggle their completion status, and delete items from the list. Here's what the app looks like in action.

Angular Todo Example 2

It utilizes the DreamFactory REST API to communicate with the backend (your DreamFactory Services Platform or “DSP” for short). If you are brand new to DreamFactory we have screencasts explaining how to get started with DreamFactory and build an app from scratch.

We also have to do list apps for other popular frameworks - a barebones example using jQuery and a mobile version using Sencha Touch.

Be sure to check out the sections at the end of this article. They show how to access our Live API Docs and how enabling CORS on your DSP allows you to run from your local machine or a service like Plunker.

Running and Exploring the App

This section shows you how to run the app and understand how it's put together. To skip straight to the code walkthrough click here.

We're assuming that you have access to the admin console for your DSP. If you don’t have a DreamFactory account, sign up here. Once you’ve signed up, go to https://<your-dsp-name>.cloud.dreamfactory.com and you can log in to the admin console. From the Applications tab look for an app named To Do List AngularJS.

Angular ToDo Image 01

This app came preinstalled on your DSP. If it was deleted or is missing for some reason you can import it by clicking the Import New App button in the upper right, selecting the To Do List AngularJS app from the list, and clicking the Import button.

Angular ToDo Image 02

Then go back to the Applications tab and it will be in the list. Click the preview button next to To Do List AngularJS.  You should see the app running on the right side of the admin console. Try adding a few items to the list. You can click the item name to toggle the completion, or click the minus to delete.

Angular ToDo Image 03

Use the source tabs in the app or click the file manager icon to view the source code for this app. These files are hosted on your DSP and can be edited live by clicking the pencil icon in the file manager. You can drag and drop files from your desktop to the file manager, or upload zip files.

We'll show you later how to run from files on your local machine for development and testing purposes.

Angular ToDo Image 04

 

Code Walkthrough

As you can see in the file manager this app consists of three files.

index.html - loads Angular and Bootstrap and has a div to hold the list. Contains the Angular markup to build the list. It has an input field and add button for adding items to the list.

app.js - functions for creating, retrieving, updating, and deleting list items and building the list

style.css - simple styling

The complete source code for this app is available on GitHub at https://github.com/dreamfactorysoftware/app-todo-angular.  You can go there to clone this repo to your local machine.  Let's dig in to the code. You can refer to the AngularJS docs for details on Angular concepts and further examples.

Looking at index.html, there is an ng-app directive at the very beginning.

<html ng-app="TodoApp">

This tells AngularJS that it will be active across the entire HTML document.

Further down we have the body tag which includes the name of the controller that will be used to manage the body content. In this case it is TodoCtrl in app.js.

<body ng-controller="TodoCtrl">

When the app starts up the controller makes a call to the REST API by calling Todo.get().

var TodoCtrl = function ($scope, Todo) {
    "use strict";
    $scope.action="Add";
    $scope.Todos = Todo.get();
    $scope.addItem = function(){
        $scope.todo.complete = false;
        Todo.save($scope.todo, function(data){
            $scope.Todos.record.push(data);
            $scope.todo={};
        });
	...
}

Dependency injection is used to give the controller access to this resource. Note the second argument to the controller is Todo, which is also the name used in the factory definition.

TodoApp.factory('Todo', function ($resource) {
    "use strict";
    return $resource('/rest/db/todo/:id/?app_name=todoangular&fields=*', {}, 
      { update: { method: 'PUT' }, query: {method: 'GET', isArray: false} });
});

The URL is specified in TodoApp.factory. Each request must include the name of the app making the request. Setting the query parameter app_name to todoangular accomplishes this. This retrieves all records from the database table named todo. On success, an array of records is returned such as?

{"record":[{"id":"35","name":"sdf","complete":false},{"id":"36","name":"fds","complete":true},{"id":"38","name":"sdf",
 "complete":false}]}

The returned array of records is added to the scope variable $scope.Todos.

The body contains a div that holds a table of todo list items. In index.html, ng-repeat loops through each record in $scope.Todos and adds a row to the table. Column 1 of the table is for the delete icon. Column 2 is for the item name. The database id of each item is used to build the <tr> element id.

<tr ng-repeat="todo in Todos.record" id="row_{{todo.id}}">

ng-class is used to determine if the item should have a strikethrough to indicate completion.

<td ng-class="{strike:todo.complete}" id="item_{{todo.id}}" style="width:100%" ng-click="updateItem()"><b>{{todo.name}}</b></td>

When you enter a new item and click the Add Item button, the function addItem() is called.

$scope.addItem = function(){
        $scope.todo.complete = false;
        Todo.save($scope.todo, function(data){
            $scope.Todos.record.push(data);
            $scope.todo={};
        });

    }

We need two values to create the new item, the name and completion status. The name of the new item comes from the input field in the html. This is because the input field for the item name is bound to the name field of the todo table using ng-model.

<input ng-model="todo.name" placeholder="Add Item" type="text" />

This means that $scope.todo.name will be set to the value of the input field. Since it's a new item we will set $scope.todo.complete to false.  We make a POST request to the same URL as we saw before with Todo.get().  The POST data is an array of JS objects but in this case there's only one element in the array. On success the new record is added to the scope, which automatically updates the DOM to add it to the table. Setting $scope.todo to {} clears the input field since that element is bound to $scope.name which is now undefined.

You can click an item in the list to toggle its completion status. Each time you do this the function updateItem() will be called.  Since only a single record is being updated the id is appended to the URL such as /rest/db/todo/37. On success the scope is updated with the new completion value which causes Angular to toggle the strikethrough in the UI.

$scope.updateItem = function () {
        var todo = this.todo;

        if(this.todo.complete === false){
            this.todo.complete = true;
        }else{
            this.todo.complete = false;
        }
        $('#item_' + todo.id).toggleClass('strike');
        Todo.update({id:todo.id}, todo, function () {
            updateByAttr($scope.Todos.record, 'id', todo.id, todo);

        });
    };

You can click the minus button next to an item to delete it from the list. Each time you do this the function deleteItem() will be called.  It makes a DELETE request with the id appended to the URL such as /rest/db/todo/37. On success the item is removed from the table by fadeOut(). This leaves the item in $scope.Todos but not visible. See if you can figure out how to remove the deleted item from $scope.Todos and let Angular remove it from the table.

$scope.deleteItem = function(){

        var id = this.todo.id;
        Todo.delete({ id:id }, function () {
            $("#row_" + id).fadeOut();
        });
    }

REST API Live Docs

To learn and experiment with the REST API you can access the Live API Documentation from your DSP's admin console.

Angular ToDo Image 05

Running Locally

The above example app shows how to run code that is hosted on your DSP. For development and testing purposes it is often helpful to have the code on your local machine and still make the same API calls to your DSP.  In this case you can turn on CORS to prevent the browser from enforcing the same-origin policy.  Go to the System Config screen in your DSP admin console and add * as the Host for CORS Access.

Angular ToDo Image 06

You may want to enable guest users and assign them a role that gives them access to your app.  A guest user can make API calls without being logged in, with access limited by the assigned guest role.  After making these changes on the System Config screen you can access your DSP directly from your local machine.  Just change the DSP URL to point to your DSP such as https://dsp-foo.cloud.dreamfactory.com.  Then open your local index.html in your browser.

Running from Plunker or JSFiddle

With CORS enabled you can also use tools like Plunkr or JSFiddle to run your apps.  Here's a link to a plunk for the AngularJS to do app.  You can change the DSP URL from dsp-go.cloud.dreamfactory.com to your own DSP <your-dsp-name>.cloud.dreamfactory.com.

Conclusion

That about covers the specifics of this app. If you have any questions or comments please contact us at support@dreamfactory.com. Your feedback is important to us!