Monday, July 5, 2010

ExtDirect GridPanel w/ Connect on NodeJS!

8/21 Update: I've updated the sample code to work with:
  • NodeJS v0.2.0+
  • Connect v0.2.4+
  • Mongoose  v0.0.2+
  • MongoDB v1.6.0
The Inspiration

So okay, earlier this year I stumbled upon NodeJS and MongoDB and I thought eureka! Finally, I can do front to back JavaScript from the display all the way to the DB and rid myself of all of the complexities and transformations that I had to deal with in my last major project.

That one was an ExtJS interface plumbed via DWR to a Java back-end, utilizing Hibernate to access a MS SQL Server DB. Hibernate has some awesome capabilities and DWR makes bridging the browser to server gulf a breeze (especially using, but I was so yearning for something more direct and simple. It seemed like such a hassle overall to get data back and forth.

The Rationale

When I found NodeJS I thought, sweet! I've got JavaScript and JSON on both sides, so no more extra overhead needed there. I had already come to understand and appreciate asynchronous behavior so Node's message hit home there. And when I found MongoDB I was ecstatic! No more relational to object mapping anymore! My objects (documents) are already in the database.

The Process

So, once I got my new laptop in May, I started down the path of educating myself on this new world whenever I found some free time. As with anything new, there are difficulties and bumps on the road. Since all of these server side components can only effectively be run on Linux (or OSX), I had to learn and setup an Ubuntu guest on VitualBox and install and configure all of the relevant bits before I could even start coding! That alone was many hours of fun there I can assure you... :) Fortunately for me, I had been using Ubuntu for at least a year on my previous old and sad laptop. So at least I had some experience navigating it and besides, Ubuntu makes Linux about as easy as it can be.

So with that all setup, I slowly took the next baby steps. I ran the obligatory Node "Hello World" app. Then by this point the ExtJS (Sencha) folks had just released Connect. I loved working with ExtJS, so I immediately jumped on that and ran all of the examples and thought how I could build out a working ExtJS example app? Since they didn't have an Ext.Direct provider, I first went down the JSONRPC path and reworked one of the ExtJS grid examples to pull data from my Node server using all of those components. But then I realized how much more work I'd have to do to get all of the other CRUD interfaces plumbed so I switched gears and went with Ext.Direct and built out my own Connect provider for Direct.

Once the basics of the Direct provider were working it was time to turn to MongoDB and complete the full data life cycle. While searching for the appropriate driver I found Mongoose which sort of claims to be an ORM, but since MongoDB already stores data as document objects, I would say Mongoose is more of a convenience layer that makes interacting with Mongo much less tedious and helps to make your code more clear and concise.

The Results

So I ended up with a slightly contrived example, but it does exercise all of the general CRUD type grid operations including sorting and paging.

The main application code itself is comprised of 3 files:
  1. CompanyGrid-ui.js - the Ext grid UI layout code (the view)
  2. CompanyGrid.js - the "business logic" extension of the view (the controller)
  3. app.js - the server side RPC data access layer (the model) and server.
Of course there are other files like the Testr.html which starts up the app and pulls in all of the required resource and library files (CSS, images and ExtJS).

In a more proper solution, the app.js would probably be broken into multiple files.  A quick rundown of this code reveals three main sections.  The first being the model definition for the Company class and the database connection and the MongoDB data initialization via Mongoose.

The second section includes the direct provider handler that manages all of the client data requests.

And the last piece basically starts the Node server via Connect and adds the appropriate middleware and configuration.

For this app, the server environment includes the following open source projects:
As of this writing, the Connect library does not include an Ext.Direct provider and I have hacked my own based on their JSONRPC provider.  In my configuration I have placed this directProvider.js file within the \lib folder under my application path on my server.

A consolidated zip archive of the project files including the direct provider and a layout of the project folders can be found at this forum post.  In my setup I have the connect folder symlinked under the project's lib folder.

Saturday, July 3, 2010

Ext.grid.GridPanel and column sorting...

Tip: Do not use the field mapping option when enabling column sorting on a grid and just rely on the ColumnModel dataIndex to properly map property values from your source data. The reason being is the field name is passed on the sort parameter field value to the server and not the mapped property name. So if you do map a field, then you will have to manage the field name on the server side injecting display logic into your operations layer.