Monday, July 8, 2013

Managing Events with Ext JS 4.X


One of the challenges with creating a large single page application with Ext JS 4.X is Event Management. Each click event of the view needs to be (or usually is) wired up in the controller class method. If your controller manages several views, this can lead to a lot of event wiring.
With the Ext JS 4.x framework, there are several ways to wire up your events.  The two that I see the most of are:
1  
1  1)  In the controllers init function, a call to the this.control({}) method is used with the component’s selector to wire up its event to the event handler.

'containerAlias > container button[name=search]': {
     click: this.onCustomerSearch
},
'containerAlias2 container[name=controls] button[name=someaction]': {
     click: this.onSomeAction
},
'containerAlias > container button[name=save]': {
     click: this.onSave
},
'someAliasName button[action=close]': {
      click: this.onClose
},
'SomeAliasName button[name=cancelMe]': {
      click: this.onCancel
},
... (continues…)

The biggest issue I’ve have with using this pattern is that this method call get very, very, very long.  As the number of components in a view or views increase, this method call gets longer and longer.  Also, if the view structure changes, you usually have to come back to change the selectors. This can be time consuming, depending on how many components and events you have.

See the Sencha docs for more information on control method in the Controller class:





2    2)   Another way is to query the container in afterrender event handler and to get each component wired up.

OnContainerRender: function (container) {
        Var searchBtn = container.down('button'),
            addBtn = searchBtn.next(),
            saveBtn = addBtn.next(),
            editBtn = saveBtn.next(),
            isActive = container.down('checkbox'),
     grid = container.down('grid');

        searchBtn.on('click', this.onSearch, this);
        addBtn.on('click', this.onAdd, this);
        saveBtn.on('click', this.onSave, this);
        editBtn.on('click', this.onEdit, this);
        isActive.on('change',this.onIsActiveChange, this);
        grid.on('select', this.onGridSelect, this);

       
},

Again; if the container structure changes, you may have to change the components selector in the up and down methods.  For example if the you added another button before the search button, you would have to change the container.down('button'), to container.down('button').next();.

           See the Sencha docs for more information on up and down method of the Element class and the 
           afterrender event:





Lately I’ve been working with the idea of just having the view expose the events you want to wire up in the controller. This pattern cuts down on the amount of code in the controller and it makes managing of view changes easier.

In the view, override the initComponent method and expose the events with the addEvent method

Step 1:

initComponent: function () {
        this.addEvents({
            save: true,
            close: true,
            select: true,
           
        });
        this.items = this.createItems();
        this.callParent(arguments);
 },


See the Sencha docs for more information on the initComponent and addEvents methods

Step 2:

In the view definition, wire up the components events in the listeners object and have the handler fire the views corresponding event.

//me is a variable to the view (var me = this;)
{
  text: 'Save',
    listeners: {
      click: function (btn, e) {
        me.fireEvent('save', me); //calls the view level event    
      }
  }
},
... Grid definition
listeners: {
    select: function (grid, record, index, e) {
              me.fireEvent('select', me, record, index); //calls the view level event    
    }
}


Notice that you can tailor the arguments that are handle by the view event listener. You can add or cut down the number of arguments needed

See the Sencha docs for more information on the listeners object http://docs.sencha.com/extjs/4.2.1/#!/api/Ext.util.Observable-cfg-listeners

Step 3:
In the controller, wire up the events on the view.
This.control({
     'AliasNameForView’: {
             save: this.onSave,
             close: this.onClose,
             select: this.onQQSelect
      }
});

See the Sencha docs for more information on control method in the Controller class:


The benefits with this pattern are as follows:

1       1) Instead of having to wire up each component separately outside the view, it allows for the isolation of the events to the view itself.

2    2)  The amount of code in the controller to wire up the events is cut down.

3    3) If the structure of the view changes, the code in the controller to wire the event does not have to change.  This allows for better code management.


As we start creating more and more “Single Page Applications” (SPA) web applications and move more business login to the client site, we have to work on better JavaScript code management.  These applications will get very large and we all know that applications change throughout their existence. More we can do to manage the code better will benefit us in the long run.

Thursday, June 27, 2013

Stand Up to Building a Better Product

Okay, this post is related to developing our desktop to web app but in a different way – health. I sit all day and sketch wireframes, explore UI designs, read emails, and then sit some more for research and creating mockups, then some more for lunch, and then in meetings, as well as the commute to and from work. Sit, sit, sit.

Transition: I made a conscious effort to get up more by putting a timer app on my computer that reminded me to get up and move, but really, I needed a reminder to stand, c'mon? I tried stretching at our daily stand-up meetings and doing the occasional squats, but nothing consistent. Reading emails and articles while standing was okay, but hunching over wasn't the most comfortable. I needed to go a step further.

All in: So after a while I thought, how about the opposite. Why not stand all day? Get the blood moving, muscles working, and sit when I need a rest. Now stretching happens more regularly, and although I do have to sit once in a while I'm standing a good 6.5-7 hours per day. Mentally I feel better, I think I'm more focused and less lethargic which I believe makes me think clearer. And if I'm thinking better, then my roll in helping to build the software will be that much better as well. 

I started a blog (standing@work) with really short entries to give people a sense of how I feel during the transition period and what thoughts I'm having while trying this new life style. I sure hope it lasts!


Here are some articles that discuss the problems of sitting all day.
What are the risks of sitting too much?

Monday, June 17, 2013

One benefit of using DeftJS in an ExtJS project.


Sencha has advanced ExtJS over the last several years. While many improvements were implemented, the introduction of MVC – model, view, controller pattern - has greatly added in code maintainability and in creating clear separation of concerns. The model represents an entity, an object where the fields of the entity are defined. The view concentrates on providing a definition of visual components. The logic then is handled in the controllers.

Given this breakdown, let’s look at the controllers and the views. The controllers in the MVC are singletons which means there is only one instance of any given controller in the application. Then that instance is responsible for handling, what may often be, a complex view, consisting of many components and sub views. Since all the logic and event handling is done in the controller, the class can become quite big. It becomes an art to know how to best break down the complexity of one controller into multiple ones. However, aside from that, what emerges as a bigger problem is the ability to unit test the controller. Singletons, as we know, are not unit test friendly. Additionally, traditional ExtJS controllers don’t support injecting dependencies that would provide an ability to use mock data on demand.

This is where DeftJS can help. DeftJS is a component that works with ExtJS and provides extra functionality including dependency injection. Controllers in DeftJS are light view classes that are view specific. By default, they are not singletons (but they can be if desired). Specific views are  controlled by controller classes, which are destroyed when views are destroyed.  This modular approach, coupled with the dependency injection, provides much better support for unit testing ExtJS applications.

Sencha has endorsed DeftJS by including DeftJS documentation on its website and presenting DeftJS at the Sencha Con.

More information can be found at:

Tuesday, June 11, 2013

MSSQL 2012: flattening a parent-child relationship using an XML 'CSV' trick

Ever been faced with a scenario where you know that a particular data relationship will 'always' have a limited number of children, and your UI requirements require tight coupling of parent data with the child collection?  

Sounds like we're about to travel thru a longish diatribe of data normalization do's and don'ts.    Dont worry, bee happy, we's not!

I'm writing this simply to document something that employs a fairly obscure but quite useful T-SQL "XML" technique.. that does just this, putting some powerful 'data-shaping logic' in your hands.

Example:   you have a parent table called 'parent' (and a child collection, called, of all things, 'child').  

The parent table has this structure:

id
parentName
address

The child table has this structure:

id
parentId
childName


Your current app requirements, for example, describe a read-only display, where there is no need for 2 related 'models' to be carried down from server to client.

You want to return, in one stored proc call, a result set that looks like this:

id, parentName, address, "childname1, childname2, childnameXX"

To make life super-easy for UI rendering, we want to return 4 columns.. the 4th being a concatenated 'CSV style' list of related children-properties.. in this case, their names).

Here's the Parent Table

the Child Table

the Stored Procedure ResultSet

And finally, working code follows for the T-SQL Stored Procedure:

Hope you find this as useful as I have.   Enjoy!      -bob



CREATE PROCEDURE  getParentsWithChildrenNames
AS

-- first, we declare a table-var to shape the final result set:

declare @tbl TABLE 
 (
id int,
parentName varchar(100),
address varchar(100),
        childNames varchar(max)
 )

 declare @tblChild TABLE 
  (
parentId int,
childName varchar(100)
  )

INSERT INTO @tbl (id,parentName ,address ,childNames) 
SELECT id, parentName, address, ''
FROM Parent

INSERT INTO @tblChild (parentId, childName ) 
 SELECT  parentId, childName
  FROM child C   
  INNER JOIN parent P on C.id = P.id

-- use 'group-by concatenation' to flatten: (this trick relies upon a well-known XML PATH undoc'd feature, which allows children to be efficiently concatenated) 
UPDATE @tbl
SET childNames = C.childrenString
FROM (SELECT p1.parentId,
  ( SELECT (rtrim(childName) + ',')  
  FROM @tblChild p2
 WHERE p2.parentId = p1.parentId
 ORDER BY childName
FOR XML PATH('') ) AS childrenString
 FROM @tblChild p1
 GROUP BY parentId) C

SELECT * FROM @tbl ORDER BY parentName


-- getParentsWithChildrenNames


Wednesday, May 29, 2013

WebSockets

Although WebSockets haven't been around for a long time, we view them as a real game changer when it comes to creating Line of Business applications (LOB) on the Web.  They provide the ability to have real-time messaging between browser clients.  No longer do we have to have the browser polling the server on an scheduled interval to determine what is going on in the application (polling can take up valuable server side resources). Now the server can send message directly to the browser in real time when needed.

WebSocket technology has been included in all the major browsers and several server side applications have been developed to support WebSockets.  Some of the server side solutions we have looked at are:

      Name a popular language and I'll bet you someone has created or is creating a WebSocket Server application with it. 

But this post is not about what WebSockets are or how to develop them.  There are several postings on the web that cover them far better than I can. If you need to understand more about WebSockets, I would recommend starting at  http://www.websocket.org for more information..

What I'd like to talk about is what problems WebSockets can solve for us. We have several requirements for our application that we are exploring the use of WebSockets. Here are a few (but not all) that we are looking at:

  1. Record locking
  2. Real time scheduling/status updates
  3. Build in Instant Messaging (IM)
  4. Administration functions (ie: seeing active users, system shutdown notification, etc.)
  5. And more....

Each one of these topics is a blog post in itself.  I've decided to narrow it down to one “Record locking;” look for posts about others in the future.

One of the major challenges in creating multi-user web applications is managing concurrent access to a data record for updates.  Because HTTP is stateless, the challenge is to develop a way to prevent and handle change conflicts. I've seen several solutions developed and used in the past.

Record lock bit: 
This solution entails creating a bit column in the table to flag a record as locked.  When a user is about to edit a record, the record is updated with a lock bit that would prevent others from editing the same record.  This requires the browser to make a request to the server to update the record.  When another user tries to edit the record, it would first check to see if the lock bit is set. If it is, the user would not be allowed to edit the record.  The challenge with this solution is that the user does not have any real time notification when the record is unlocked. The browser would have to constantly poll to see when the record is free.  Additionally if the user’s (the one editing the record) computer crashes the lock bit could be left in a lock state. This would prevent anyone from editing the record until the lock bit is cleared.  Both of these challenges can be solved but it would take some complex coding.

Versioning:
Another solution is to put a version number with each record.  When the user views a record, the records version number would be retrieved with the record.  When user edits the records and saves, the server side code would first verify that the record has the same version number; if it does the user is free to save the record.  If the version number is different, the server would prevent the save and would notify the user that the record was updated by someone else.  At this time, the challenge is what to do with the unsaved data. Some solutions would be:

  • Code the application to try to merge the changes
  • Just have the user discard their changes and re-enter them

These options would require a good chunk of coding or an angry user.

WebSockets:
With WebSockets, we are looking to have the client be notified in real time that some else is editing the record.  When a user wants to edit a record, a notification is sent out to any client that is viewing the same record.  At that point the other users would not be able to put the record into “edit” mode. The edit button would disabled and a message would be displayed like “User John Doe is currently editing”.  When the record is saveed or editing canceled, a notification would go out to the any user viewing the record.  This notification would trigger the edit button to be enabled on the other clients. It would also send updated record data to the display. Each user viewing the record would see the updates in real-time.

We are currently in the prototyping phase of this solution and as we learn more I will post about our findings (what worked, what didn't, etc)

Wish us luck.


Tuesday, April 23, 2013

Creating animations using ExtJS and Ext.fx.Anim



CSS3 provides an ability for creating animations by gradually changing a style of an element. Any number of styles can be changed during a transition and there could be any number of transitions composing an animation. Animations in CC3 are created by specifying the “to” and “from” values or the @keyframe rule. With the @keyframe rule we define the steps starting from 0% and ending at 100 %. To be browser compatible, both 0% and 100% should be defined.

ExtJS has built-in classes to create animations using the CCS3 conventions. The two classes providing this functionality are Ext.fx.Anim and Ext.fx.Animator. Ext.fx.Anim accepts the “keyframes” configuration and passes the work to the Ext.fx.Animator . Following is an example of a simple animation using Ext.fx.Anim and  keyframes. The keyframe event generated at each transition will log a current step’s number. While this is might not be a real life example, a similar animation could potentially be used to alert users that a record is being edited by someone else at the same time and give them choices on the next course of action .


var myComponent = Ext.create('Ext.panel.Panel',{
    renderTo: Ext.getBody(),
    width: 270,
    itemId: 'myPanel',  
    style: {
        width: '10px',
        height: '10px',
        'background-color': '#5687FF'
    },
    defaultType: 'textfield',
    items: [{
        fieldLabel: 'First Name'
    }, {
        fieldLabel: 'Last Name'
    }]
});
Ext.create('Ext.fx.Anim', {
    target: myComponent.getEl(),
    duration: 8000,
    keyframes : {
        '0%': {
            opacity: 0.6
        },
        '60%': {
            x: 120,
            y: 120,
            opacity: 1
        },
        '80%': {
        },
        '100%': {
            x: 0,
            y: 0,
            opacity: 0
        }
    },
    listeners: {
        keyframe: function(o, n) {
            console.log('transition:', n);
        }
    }
});

More information about  Ext.fx.Anim can be found at the Sencha's site.

Tuesday, April 16, 2013


Dapper and JSON:  performance and code simplicity.   You just may like this Micro-ORM.

If you are writing JavaScript apps that are data intensive you might want to take a look at Dapper.   Dapper is a super lightweight (single-file) object-mapper for .NET that’s been getting a lot of respect.  Per Wikipedia:  “Dapper was started by Sam Saffron because of the N+1 and other performance issues with Entity framework


You can even now download Dapper via NuGet from VS2012.

I’ll tell you why my team is so excited about Dapper.  Many people have heard about Dapper’s performance.  Sam Saffron designed Dapper to be FAST.  It is fast.   However, that’s not the biggest win for us.  I’ll explain.

First, a quick note about the team and the project.  We’re a team of 5 working on a multi-year rewrite of a legacy healthcare app.  The app is data-intensive with a large schema, extremely detailed UI, and complex business rules.  We’re using ExtJS4.2, MVC4, MSSQL2012.   (Sidenote: we were using KendoUI, Knockout, MVC3 and have recently gotten religious about Sencha, the makers of ExtJS, Sencha Touch, etc.  But that’s another story, this blog is not about Sencha).


a)      Dapper has made communications with MSSQL much easier for us by making the always-fun ‘parameter boundary’ a bit easier to cross.   Take a look at these few lines of C# code in a data-layer:

Here, our server-side controller for processing an Product Master ‘Save’ receives one input ‘object’ parameter (passed to it as JSON by ExtJS code).  The stored-proc checks for potential save conflicts, and then returns another ‘object’ parameter from a single-row select executed by the stored-proc, in place of a ‘RETURN’ or ‘OUTPUT’ variable (in this particular optimistic-locking example, the biz-rule calls for returning the ‘current’ state of the row to the user if an intervening user manages to Update the same row before the ‘saving’ user commits their data.

  public JsonResult saveProduct(Product model)
{…
var  returnObj  = (IDictionary<string,object>)conn.Query("saveProduct", model, commandType: CommandType.StoredProcedure).First();
conn.Close();
return Json(returnObj  , JsonRequestBehavior.AllowGet);
…}



There’s a lot going on here.  Dapper is able to make complex AJAX-based Javascript<>SqlServer communications much easier for applications with .NET backend layers.

1)      The first parameter passed to conn.Query() is the stored procedure name, nothing special here.  However:
2)      Note that the second parameter passed to conn.Query is ‘model’.    Using this strongly-typed model (here a ‘Product’ model passed into the saveProduct method), Dapper auto-generates all parameters for the SQL stored-procedure call.  In this case, we’re saved 22 lines of ‘DynamicParameter’ declaration).
3)      Dapper also provides for ‘Multi’ (easy return of multiple result sets) and ‘Execute’ methods, but here, we use ‘Query’…  because our T-SQL Stored Procedure has been tasked with returning a result-set of ‘before’ values when it detects a multiuser collision.    When our SP detects a collision (using a table-resident DateTime column as a version stamp), it calls a JSON-generating UDF* to create a javascript object result-set that Dapper can easily cast back into a key-hash for easy server-side processing of a return-‘model’.

Here’s a fragment of the stored procedure that checks for collisions, and returns the ‘before’ state for processing client-side:
       IF @dtLastUpdated <> @tblDtLastUpdated  AND @tblDtLastUpdated IS NOT NULL
       BEGIN
              SET @lcSql='SELECT P.*,U.name AS userNameLastUpdated FROM Products P
            LEFT OUTER JOIN Users U on P.userlastUpdated=U.id where P.id =' +cast(@id as varchar(10))
              EXEC GetJSON @lcSql

              RETURN
       END
               
You can see that we did not have to declare a bunch of INPUT parameters to pass data to T-SQL from the C# layer.  Nor did we have declare a bunch of OUTPUT parameters to return a complex object back from SQL . 

Dapper is making things sooooooo much easier..

Namaste,

bob davis

*check back later for more info about JSON-generating UDFs.   I’m using one now created by an enterprising Bangalore tech.  I will be weighing in more on it and others as we continue to check it’s performance and accuracy , but so far, with the singleton-row result-set we need it for, performance is more than adequate.