Sencha Inc. | HTML5 Apps

Blog

Build a “To Do” Application with Sencha Touch, Sencha.io, and Facebook Integration

June 26, 2012 | Jason Cline

Introduction

Sencha.io ships with a suite of services that make it easy for developers to build interactive mobile applications. These services include User Login, Data (with multi-device synchronization), Channels for message queueing, and App Hosting and Deployment. All these services can help your application come to life without having to write backend code.

In this article, we’ll show you how to take advantage of Sencha.io services in a Sencha Touch application. We’ll use two of the Sencha.io services, — the User Login service to have users connect to the app via Facebook, and the Data service to store information. By the end of this tutorial, you’ll have a good understanding of how to leverage Sencha.io in your own Sencha Touch application.

Objective

We will start with a Sencha Touch "To Do" application that stores data in localStorage and converts it to use Sencha.io’s Login and Data Services. We'll then optimize the application for production using Sencha’s SDK Tools. After the application is built, we'll deploy it with Sencha.io’s Deploy service. Finally, we will enable Facebook Login on the application.

If you want to skip ahead and see the finished project live, check out the application hosted on senchafy.com: http://sio-todo.senchafy.com/. You will need a Sencha Touch compatible browser (specifically Safari, Chrome, iOS or Android)

Prerequisites

You should already be familiar with Sencha Touch 2. If you're new to Sencha Touch, we provide great documentation that will help you get started with your first app.

Get the Source Code

We have created a repository on github that contains the complete source code for this example.

Clone the git repository:

Clone git respository

On Github: https://github.com/senchaio/sio-todo-app

git clone https://github.com/senchaio/sio-todo-app.git

To make it easy to follow along there is a branch for each step of migrating the application.

git branch -a
git branch -a

If you want to follow along step-by-step to see the running application at each step of the conversion, use the git checkout command when instructed. Otherwise, you can just stay on the master branch and see the finished product.

Step Zero: A regular Sencha Touch application:

Add Sencha Touch 2.0.0 SDK

Because you already have a local copy of Sencha Touch, we didn’t include a copy in the git repository. Place a copy of your Sencha Touch SDK into a directory called "sdk" at the root the repository. After you are done with this step, your application directory should look like this:

You should be able to open the "index.html" file in either Safari or Chrome. When the application loads, it should look like this:

Application Structure

The "To Do" application follows the Sencha Touch MVC pattern and contains separate files for a Controller, Model, Store, and View:

The application consists of a title bar, a text input field docked to the top of the screen, and an Ext.List that fills rest of the screen.

Users can enter tasks in the text field and when pressing Enter, the task is added to the store that is connected to the list.

All of the layout code is contained in view/Todos.js

config: {
   layout: {
      type: 'fit'
   },
   fullscreen: true,
   items: [
      {
         xtype: 'titlebar',
         docked: 'top',
         title: 'ToDo',
         items: [ {
            xtype:"sioAuthButton",
            align: "right"
         }]
      },
      {
         xtype: 'textfield',
         id: "todoinput",
         docked: 'top',
         labelWidth: '0%',
         placeHolder: 'New Task',
         disabled: true
      },
      {
         xtype: 'list',
         itemTpl: [
            '{task}'
         ],
         disabledSelection: true,
         store: 'todos',
         grouped: true
      }
   ]
}

The store just uses a local storage proxy to persist the data on the local device. It has a grouper and sorter so that all the completed and uncompleted tasks are grouped together:

store/Todos.js

config: {
   autoLoad: true,
   model: 'MyApp.model.Todo',
   storeId: 'todos',
   proxy: {
      type: 'localstorage',
      id: 'todos',
   },
   autoLoad: true,  // set auto load to true so that any local data will
                    // populated in memory
   autoSync: false, // Wait until we have an authenciated user to
                    // and call manually. see MyApp.controller.Todos
   grouper: {
      groupFn: function(record) {
         return record.get('completed') ? "Complete" : "Tasks";
      },
      sortProperty: 'completed'
   },
   sorters: [
      {
         property : 'timestamp',
         direction: 'DESC'
      },
      {
         property : 'task',
         direction: 'ASC'
      }
   ],
}

controller/Todos.js contains the bulk of the application’s code. It connects the events generated by the view to actions on the store.

config: {
   /**
   * Add controls for both the text input and the todo list.
   */
   control: {
      textInput:{
         action: "addTodo"
      },
      list: {
         itemswipe: "toggleTodo"
      },
   },
   refs: {
      list: "list",
      textInput: "#todoinput"
   }
},

When the user swipes on a list item, the controller will flip the record from completed false to completed true. After adding several tasks and completing a few of them, the application should look like this:

Bring the App to Life with Sencha.io

This application is useful as it allows the user to keep track of their tasks, however it has some significant limitations. All of the user’s data is stored on the browser’s local storage. There is no guarantee that this data will be around when the user needs it. If the user clears their browser data or the operating system needs extra space, local storage may be erased — deleting the only copy of the user’s data. Most users tend to have more than one device where they access their information. When the user access the site on a different device their tasks will not be there. By following the next few steps, a developer can quickly solve all of these problems.

To start using Sencha.io you first need to login to the developer console.

Your Sencha.io account is the same as your Sencha Forum account, so no registration is required if you alredy have a forum account.

First, create an application by clicking on Apps, then Create App

Give your application a name. The name of your app will be in the URL of your deployed application.

Next create a user group for the application. A user group is how we keep track of all of the users who register to use the application. Do this by clicking user groups, and then create usergroup:

Give the group a name. Groups can be shared between applications or each application can have its own group. You can just give the group the same name as the application.

After the group is created, click the group name from your list of groups and then click Edit Usergroup:

Choose “in the app” for when the user should be asked to authenticate themselves:

Finally, add the group you created to your application by first clicking on Apps in the main nav, then the app name from the list of apps. Click the edit app button:

Select your user group from the user group dropdown.

Now you have an application that will use Sencha.io’s built in user accounts. Users will be able to register and use your application directly from within the app.

Add the Sencha.io SDK to your application:

Create an io directory in the root folder of the example application. Copy the src and lib file from the downloaded copy of the Sencha.io SDK. Your application directory should look like this:

Now we need to add Sencha.io to the application code.

First we need to tell the dynamic loader where to find Sencha.io:

Ext.Loader.setPath({
    'Ext.io': 'io/src/io',
    'Ext.cf': 'io/src/cf'
 });

Next add io to the application’s config:

config: {
    io: {
        appId: "5ZarPd0Cu6XyZC15AVHTE1BXq6C",
        appSecret: "xlK93iMvE8nsYEfk"
    }
 },

Copy your appId and appSecret from the developer console:

Next add Ext.io.Controller to the list of application controllers:

controllers: ['Ext.io.Controller', "Todos"],

Ext.io.Controller manages the connection to Sencha.io and fires events the application can interact with.

Now re-load the application in the browser and you should see a login screen:

You now have an application that requires a Sencha.io account. You can create a new account by tapping the register button at the top right of the screen.

After you login or register, you will be taken back to the main view of the "To Do" list. To finish the user management portion of the example, we will add a button to the title bar. Sencha.io proides a component called Authbutton that will handle the login and logout of a user. It will automatically display the correct label depending on if the user is authenticated or not.

In view/Todos.js add "Ext.io.ux.AuthButton" to your requires:

requires: [
     "Ext.TitleBar",
     "Ext.dataview.List",
     "Ext.io.ux.AuthButton"
   ],

And an xtype of “sioAuthButton” as a child of the toolbar:

{
       xtype: 'titlebar',
       docked: 'top',
       title: 'Todo',
       items: [ {
             xtype: "sioAuthButton",
             align: "right"
       }]
  },

Now, when you reload the application you should see a login/logout button in the toolbar:

Data

Now that we have a user that can login to the application, we need to convert the store from local storage to a store that can synchronize with the cloud.

Sencha.io provides a proxy that will store data locally, using local storage, and keep that data synchronized with the cloud, appropriately called syncstorage.

In store/Todos.js change
proxy: {
     type: 'localStorage',
     id: 'todos',
 },

to

proxy: {
      type: 'syncstorage',
      id: 'todos',
      owner: 'user',
      access: 'private'
 },

Now, whenever the application calls sync the data will be synchronized with the cloud. We also added the additional properties of owner and access. We are creating this store as user/private so only the user can access the data.

Next, we need to make some changes to the application’s controller to take full advantage of our new store.

First, we need to add an init method to our controller and listen for some events generated by Ext.io.Controller:

init: function() {
       this.getApplication().sio.on({
           authorized: this.onAuth,
           logout: this.onLogout,
           usermessage: this.onUserMessage,
           scope: this
       });
},

Note: When you add Ext.io.Controller to your application, it adds aproperty to the application object called "sio." Your application code will have easy access to its events and methods.

The app needs to wait to sync the store until after the user has authenticated. When the authorized event fires, we call sync on the store:

onAuth: function(user) {
        console.log("onAuth", user);
        this.getTextInput().setDisabled(false);
        Ext.getStore('todos').sync();
        return true;
 },

When the user logs out of the application, we need to remove all of the local data associated with the "To Do" data store:

onLogout: function() {
     var store = Ext.getStore('todos');
     store.getProxy().clear();
     store.load();
     this.getTextInput().setDisabled(true);
     return true;
 },

These are all the changes we need to make for a fully functional application that stores its data in the cloud. Your users can now login on any number of devices and their data will follow them from device to device.

The existing add and update methods in the controller don’t need to be modified, they just work.

addTodo: function(textfield, e, options) {
     console.log("addTodo");
     var todos = Ext.getStore('todos');
     todos.add({
         task: textfield.getValue(),
         completed: false,
         timestamp: new Date().getTime()
     });
     todos.sync();
     textfield.setValue("");
 },

Reload your application and give it a try. At this point, you will need more than one device or browser to see how the data is replicated to everywhere that the user is logged in. You can also log out of the application, check that the data is no longer in local storage, and then log back in.

If you are testing the application side-by-side, you may notice a problem. The data is only updated after you perform an action locally that triggers a sync operation on the store. We will fix this in the next step.

User Messaging

Now there is one more example we should handle to make this an event better demo. If your users are logged into more than one device at the same time, we'll want to notify all of their devices that something has changed so they need to perform a sync. To accomplish this, we use user messaging.

First we need to add a new method to our controller:

syncCallback: function() {
    console.log("broadcast update", arguments);
    this.getApplication().sio.getUser(function(user, error) {
        if (user) {
            console.log("user", user);
            user.send({
                message: "updated"
            },
            function() {
                console.log("send callback");
            }
            );
        }
    });
}

In this method, we get the current user of the application and send them a message. The message will be delivered to all devices that the user is logged into.

Now we need to update the addTodo and toggleTodo methods so that they call syncCallback after sync completes:

addTodo: function(textfield, e, options) {
        console.log("addTodo");
        var todos = Ext.getStore('todos');
        todos.add({
            task: textfield.getValue(),
            completed: false,
            timestamp: new Date().getTime()
        });
        todos.sync(Ext.bind(this.syncCallback, this));
        textfield.setValue("");
  },

Now we are sending messages out to all of the devices the user owns. Next, we need to listen for those messages. We can do this by listening for the “usermessage” event on Ext.io.Controller.

First, update the init function:

init: function() {
        this.getApplication().sio.on({
            authorized: this.onAuth,
            logout: this.onLogout,
            usermessage: this.onUserMessage,
            scope: this
        });
 },

Then, add the onUserMessage function to the controller:

onUserMessage: function(sender, message) {
    var userId = sender.getUserId();
    console.log("user got a message!", arguments, userId);
    Ext.getStore('todos').sync(function() {
        console.log("todos sync callback", arguments);
    });
    return true;
},

To test this change, you will need to be logged in as the same user on two or more devices.

Reload the application in each of your devices and then add another task. It should automatically appear in all of the other devices. Depending on the speed of your network connection it should only take a second or two for all the devices to synchronize.

Now our application is complete. We can login a user, save data in the cloud, and push those updates in real time to all of the user’s devices.

Build and Deploy

Until now, we have been running the application on your local development environment. But if we want others to be able to access it we need to upload the code to a server. Fortunately, Sencha.io provdes a Deployment service for your applications. We just need to use Sencha’s SDK tools to build the application and upload the app to Sencha.io.

Let's begin. Open a terminal window and from the root directory of your application run the sencha command:

sencha app build package

You should see output that looks like this:

After the command completes, there should be a build directory in the root directory of the app:

The output of the build will dramatically reduce the number of files and the size of the overall application.

To upload the built application, simply ZIP the package folder using your favorite ZIP utility:

Find your application in the developer console. Click "Apps," then your application from the application list.

Next, click the create New Version button

Click browse, choose your ZIP file, and then give your version a tag to identify it:

After clicking Save and the ZIP file uploads, you can click the production link next to the version to deploy it to the web servers:

Now your application is deployed and running on the Sencha.io servers. You can access the application URL by clicking the view app link under current deployments:

If you want to have an application where the users have to create a new account to use your application, you are done. However, we promised to show you how to publish an application that uses Facebook’s API to authenticate your users.

Usually, integrating Facebook into your applications is a bit of work. And its even more work if you want to keep your own user data associated with those Facebook accounts. By now you are probably already looking for the next Git branch labeld 06_Facebook. Well, stop looking because there isn’t one. There are zero code changes required to enable Facebook logins in your Sencha.io application.

From the developer console click on user groups. Create a new user group, and then edit the user group like we did earlier in this tutorial:

Wait! We need Facebook app keys.

Hopefully you are already a Facebook developer, if not you will need to signup as a developer.

Got to https://developers.facebook.com/apps and click Create New App:

Fill out your application name:

Fill out the website and mobile website URLs to match your apps senchafy.com url:

Now, go back to the developer console and paste in your Facebook app key and secret:

If you were already logged into the application using a Sencha.io account, you should clear all local storage data from the application domain to ensure that everything switches smoothly.

Reload the application and you should see a prompt asking to login with Facebook:

Follow the prompts and login with your facebook credentials. You will be returned to the main "To Do" list screen and can start adding tasks.

Now you have an application that stores data in the cloud using Sencha.io, and allows users to login with their Facebook account.

There are 16 responses. Add yours.

Loiane

2 years ago

Nice exemple!
Thank you!

Jeff Thurston

2 years ago

Not working for me….

Did:
git clone https://github.com/senchaio/sio-todo-app.git (worked)
git branch -a (worked)
git checkout 00_basic_app (worked)
copied from Sencha (command folder, microloader folder, resources folder, src folder, version.txt, sencha-touch.js, sencha-touch-all.js)
Opened in browser receive the follow error in web inspector
GET http://localhost:8888/sio-todo-app/event/Dispatcher.js?_dc=1340833889080 404 (Not Found) Dispatcher.js
GET http://localhost:8888/sio-todo-app/event/publisher/Dom.js?_dc=1340833889082 404 (Not Found) Dom.js

These files are over in sdk/src/event in my project.

Jason Cline

2 years ago

Hi Jeff,

You need to be using Sencha Touch 2.0.0 for this example to work.  The example code was published on git before the release of 2.0.1.1

Srinivasan Mohan

2 years ago

Sweet - Nice Job io team!

cnc

2 years ago

Hi All,
I am new to Sencha, could any one tell me in short what are the differences between Commercial & GPL versions of Sencha.

Regards,
C

Aditya Bansod Sencha Employee

2 years ago

@cnc—the GPL version means the application you create needs to follow the rules of the GPL, such as open sourcing your application. The Commercial version means that you do not need to follow those rules and it’s much more like standard commercial software rules. The actual product is identical.

Dave Horan

2 years ago

Jason, great example. Well done. Is there any specific things that need to be changed for it to work on ST 2.0.1.x? This more of a Touch issue, or an SDK issue at this point?

Jason Cline

2 years ago

Hi David,

Thank you for checking out the demo. Sencha Touch and Sencha.io are tightly integrated at the data layer. We need to update the io SDK to be compatible with the changes in 2.0.1.x.

cnc

2 years ago

Hi Aditya,

Thanks for the clarification, I saw both the versions free downloadable ... do I need any permission for using the commercial version. What do u suggest which flavor a beginner should use for getting started Sencha.

Dan

2 years ago

Hi,

Nice tutorial, but the demo app doesn’t seem to work as expected (iPhone 4s)

I registered for an io account, typed a new task and hit enter then got a blank screen.

I refreshed the page and hit the login button to be told that I must login with Facebook - after registering, why can’t I login with the account I just created?

Josh

2 years ago

Hey Jason,

I am having a problem after I add the Sencha.io in. I am getting the error “Error during WebSocket handshake: ‘Connection’ header value is not ‘Upgrade’ ”

As I am still new to Sencha Touch and even newer to using Sencha.io I have no clue as to what this error means.

Any help would be really appreciated!

Jason Cline

2 years ago

Hi Dan,

Were you using the hosted example at http://sio-todo.senchafy.com/ or were you using the tutorial to deploy your own copy?

If you were using http://sio-todo.senchafy.com/ then you should not have seen a sencha.io login.

I re-tested on an my iphone 4s just now using that url and it worked as expected. But it is possible that uncovered a bug we haven’t seen yet.

Also make sure that you weren’t in private browsing mode. We rely on localstorage which is disabled when you are in private browsing mode.

We have a section on our community forums dedicated to supporting those who use http://www.sencha.com/forum/forumdisplay.php?94-Sencha.io-Community-Forums

If you could post more details about your test I’d be happy to help further debug the problem.

Jason Cline

2 years ago

Hi Josh,

I’d be happy to help get you going.  If you don’t already have a forum account http://www.sencha.com/forum you should sign up. It is a great resource for getting your Sencha related questions answered.

As for your specific issue.  The current version of Sencha.io uses Websockets to maintain a realtime connection between the client and server. Websockets are a new technology that isn’t supported on all network environments. In particular many firewalls and proxies prevent them from establishing or maintaining a connection. This is one possible explanation for what you are seeing.  For the production release of Sencha.io we will be using a variety of network transports to ensure that all devices can connect to the servers and automatically select the best one available.

In the meantime if you could post the details about your test setup on the forum we would greatly appreciate it:

http://www.sencha.com/forum/forumdisplay.php?94-Sencha.io-Community-Forums

Banner

2 years ago

The ‘Sencha Touch application’ is truly very useful to apply to create my own page. Thanks for giving every sketch of the steps. It’ll help to go forward with the right clue. Thanks Jason!

Marcus

2 years ago

Great example!  I’m working on something similar but I’m trying to use Windows Azure Access Control Service (ACS) for the Facebook authentication part. I’m having trouble getting it to work though, do you have any experience with Windows Azure ACS or know of anyone that has worked with Sencha Touch and Azure? Thanks Jason.

Sharad Chandra

2 years ago

How to append url in proxy.
There are two variable strUserId and strPassword.where strUserId =Doe and strPassword =xyz.
my url is http://localhost:51047/SenchaTest/Default.aspx I hav.e to append url like below :-
http://localhost:51047/SenchaTest/Default.aspx?Username=Doe &Password=xyz

Please suggest me as soon as posible.

Comments are Gravatar enabled. Your email address will not be shown.

Commenting is not available in this channel entry.