Monthly Archives: March 2013

Orchestrating Login and Roles-Based Security in Ext JS and Sencha Touch

The issue of logins and roles-based security often comes up in my Ext JS and Sencha Touch classes. The sad reality is that anyone who knows how to open the browser’s JavaScript debugger is able to “hack” your application. Therefore, security is something that *must& be handled at the application-server level as there is no current method to adequately secure your JavaScript code.

Having said that, most corporate apps still require logins and roles-based security as functional requirements. A user must enter credentials and their button/menu selections need to be tailored to a specified role as illustrated by the following video:

Typically, your app.js file simply invokes a login dialog as illustrated by the following code snippet:

// code listing 1: app.js
    controllers: ["Main"],
    views: ["Main"],
    name: 'LoginAppDemo',
    autoCreateViewport: false,
    launch: function() {

Let’s also assume that we’re going to put together a simple login form inside of a floating window. Why a floating window, you ask? Because login forms are always cooler if they float and are draggable, of course!

// code listing 2: LoginForm.js
Ext.define("LoginAppDemo.view.LoginForm", {
 extend: 'Ext.window.Window',
 alias: 'widget.loginform',
 requires: ['Ext.form.Panel'],
 title: 'Please Log In',
 autoShow: true,
 height: 150,
 width: 300,
 closable: false,
 resizable: false,
 layout: 'fit',
 items: [
   xtype: 'form',
   bodyPadding: 5,
   defaults: {
    xtype: 'textfield',
    anchor: '100%'
   items: [
     fieldLabel: 'User Name:',
     name: 'username',
     allowBlank: false
     fieldLabel: 'Password:',
     name: 'password',
     allowBlank: false
   buttons: [
     text: 'Log in',
     formBind: true,
     disabled: true,
     handler: function(b,e) {
      var formDialog = b.up('loginform');
      var form = b.up('form');
      // fire custom event for the controller to handle
     } // handler
    } // login button
   ] // buttons 
  } // form
 ] // items

Note that in the preceding example, when the user clicks the ‘Log in’ button, I fire a custom ‘login’ event and pass references to the login window, the login credentials form, and the data that the user entered into the form up to the controller (listed below).

From within the login handler, I make an Ajax call to the server in order to retrieve information about the user profile. In a production environment you would make this call via HTTPS to your application server (.php,.aspx,.jsp,.cfc, etc.).

// code listing 3
Ext.define('LoginAppDemo.controller.Main', {
 extend: '',
 requires: ['LoginAppDemo.user.Profile'],
 views: ['LoginForm','Viewport'],
 init: function(application) {
   "loginform": {
     login: this.onLogin

 onLogin: function(loginDialog,loginForm,loginCredentials) {
   var me = this;

   // authenticate
    url: 'resources/sampledata/cred.json',
    params: {
     username: loginCredentials.username,
     password: loginCredentials.password
    success: function(response) {
     // convert text response to javascript object
     var data = Ext.decode(response.responseText);
     // if server response contains "firstName" node, then success!			
     if (data.firstName) {
      // instantiate user info in global scope for easy referencing
      LoginAppDemo.User = Ext.create("LoginAppDemo.user.Profile", {
    					firstName: data.firstName,
    					lastName: data.lastName,
    					roles: data.roles
      // destroy login dialog

      Ext.Msg.alert("Login Successful",
    		    Ext.String.format("Welcome {0} {1}",

      // load main UI

  } else { // login failed
    Ext.Msg.alert("Invalid credentials",
                  "You entered invalid credentials.", 
                  function() {

Your app server would subsequently run a custom sql query to ensure that the passed username and password were valid and return a response similar to the following:

// code listing 4: cred.json
 firstName: 'Steve',
 lastName: 'Drucker',
 roles: 'admin'

Your app server would also set up session management for the user, typically consisting of some sort of session-based cookie hack since not every browser supports the establishment of persistent (html5 websocket) connections. Each subsequent data request to the server would use this cookie to determine whether the user had the appropriate rights to download the data that was requested.

From a UI perspective, however, we are simply concerned with caching the user’s identity and roles information in a location that could be easily accessed by our view and controller logic. Lines 33-37 of code listing 3 above instantiate the custom component described in code listing 5 at the root of your application’s namespace for easy global access.

// code listing 5
Ext.define("LoginAppDemo.user.Profile", {
  config: {
    firstName: '',
    lastName: '',
    roles: []

  isUserInRole: function(roles) {
   for (var i=0; i<roles.length; i++) {
    if (Ext.Array.contains(this.getRoles(),roles[i])) {
     return true
   return false;

  constructor: function(config) {


As illustrated by the following toolbar class, once the framework described above is in place, you can simply test the features of your app before outputting them to the user.

Ext.define("LoginAppDemo.view.MainToolbar", {
 extend: 'Ext.toolbar.Toolbar',
 alias: 'widget.maintoolbar',
 requires: ['Ext.toolbar.TextItem'],
 initComponent: function() {
  var items = [
    xtype: 'tbtext',
    text: 'Login and Roles-Based Security Simulator'
    xtype: 'tbfill'

  if (LoginAppDemo.User.isUserInRole(["admin"])) {
   items.push({ xtype: 'button', text: 'For Admins'});

  if (LoginAppDemo.User.isUserInRole(["admin","users"])) {
   items.push({xtype: 'button', text: 'For Admins or Users' });

  if (LoginAppDemo.User.isUserInRole(["nobody"])) {
   items.push({xtype: 'button', text: 'For nobody' });

  Ext.apply(this, {items: items});

Ext JS and Sencha Touch Charts Drill-Down

The “trick” to implementing drill-down on Sencha Touch and Ext JS 4 charts is to use the completely undocumented itemmousedown event listener as illustrated on lines 20-24 below. Note that this technique is compatible with both Sencha Touch 2.0+ and Ext JS 4.0. Use console.log() in the itemmousedown handler to determine how to access the underlying data record as the referencing varies depending on platform and type of chart series.

var chart = new Ext.chart.PolarChart({
    animate: true,
    interactions: ['rotate'],
    colors: ["#115fa6", "#94ae0a", "#a61120", "#ff8809", "#ffd13e"],
    store: {
      fields: ['name','data3'],
      data: [
          {'name':'metric one', 'data3':14},
          {'name':'metric two', 'data3':16},
          {'name':'metric three', 'data3':14},
          {'name':'metric four', 'data3':6},
          {'name':'metric five', 'data3':36}
    series: [{
        type: 'pie',
        labelField: 'name',
        xField: 'data3',
        donut: 30,
        listeners: {
           itemmousedown: function(a,b) {
            Ext.Msg.alert("You clicked!",  b.record.get('name') + "(" + b.record.get('data3') + ")");

Animating components in Sencha Touch 2

I’m working on a big Sencha Touch project that involves a *lot* of interactivity and animations. Since I’d never had the need to implement custom animations in Sencha Touch 2 beyond the typical card layout transition, I thought it would be a good idea to throw together a simple example to see how the Ext.Anim singleton operates. As you can see from the code snippet below, it’s actually rather simple to animate a swap of two components in an hbox configuration!

In this particular use-case, the Ext.Anim class dynamically adds a CSS3  -webkit-transform: translate3d() property to the affected container’s DOM element. When the animation has been completed, the CSS3 is stripped and the components are physically reordered within their parent.

Ext.define('MyApp.view.MyContainer', {
 extend: 'Ext.Container',

 requires: ['Ext.Anim'],

 config: {
  itemId: 'main',
  layout: { type: 'vbox' },
  items: [
    xtype: 'container',
    itemId: 'boxcontainer',
    layout: { type: 'hbox' },
    items: [
      xtype: 'component',
      flex: 1,
      html: 'Container 1',
      itemId: 'box1',
      style: 'background-color: red;',
      styleHtmlContent: true,
      width: '50%'
      xtype: 'component',
      flex: 1,
      html: 'Container2',
      itemId: 'box2',
      style: 'background-color: green;',
      styleHtmlContent: true
    xtype: 'button',
    margin: '40 5 5 5',
    text: 'Animate',
    handler: function(button, event) {

     // get pointer to box 1 DOM element
     var box1 = button.up('#main').down('#box1').element;

     // get pointer to box 2 DOM element
     var box2 = button.up('#main').down('#box2').element;

     if (!this.rotated)
      this.rotated = true;
      this.rotated = false;

     // animate box 1 - note this is an async operation,'slide', {
        direction: 'right',
        reverse: !this.rotated,
        duration: 1000,
        easing: 'ease',
        autoClear: true,
        after: function(el) {
          // swap physical positions after animation
          var parent=button.up('container').down('#boxcontainer');

     // animate box 2,'slide', {
       direction: 'left',
       reverse: !this.rotated,
       duration: 1000,
       easing: 'ease',
       autoClear: true

   } // handler
  } // button
 ] // items
} // config