Monday, 7 April 2014

ExtJS grids with Locking Columns

There may be grids where in two or more columns are required to be shown at all times even if there are many columns available. In such a scenario, we can lock a few columns which will prevent them from getting hidden when attempting to scroll sideways along the grid. A similar functionality is present in MS Excel where in a column can be locked from scrolling away.


Here’s what we will build in this post.




To use locking functionality we must explicitly specify the LockingColumnModel and the LockingGridView.

NOTE: Two imports need to be added for the locking grid to work.

<link rel="stylesheet" type="text/css" href="../ux/css/LockingGridView.css" />
<script type="text/javascript" src="../ux/LockingGridView.js"></script>

The modified grid,

var grid = new Ext.grid.GridPanel({
                store: empStore,
                colModel: new Ext.ux.grid.LockingColumnModel([
                                {header: 'Emp No.', width: 100, sortable: true, dataIndex: 'emp_no', align:'center', renderer: showEmpDetails, locked: true},
                                {header: 'Last Name', width: 100, sortable: true, dataIndex: 'last_name', locked: true},
                                {header: 'First Name', width: 100, sortable: true, dataIndex: 'first_name'},
                                {header: 'Age', width: 75, sortable: true, dataIndex: 'age'},
                                {header: 'Date of Joining', width: 100, sortable: true, renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'doj'},
                                {header: 'Address', width: 400, dataIndex: 'address'}
                ]),
                stripeRows: true,
                height: 350,
                width: 400,
                title: 'Employee Details',
                view: new Ext.ux.grid.LockingGridView(),
                renderTo: Ext.getBody()
});


Setting ‘locked’ to “true” for a column would prevent it from getting hidden on scrolling.

The user would also be allowed to decide on which columns to lock, unlock. Clicking on the column header would show up two mutually exclusive options, Lock and Unlock.

Columns already locked can be unlocked by the user and vice versa.

Here’s the JSFiddle -> JSFiddle Locking Grid

Wednesday, 2 April 2014

ExtJS grids with cell & row renderers

In this post I will focus on cell and row renderers. It is often desired to provide external references to the data present on the grid. One simple way is to present the user with a hyperlink on selected columns. This is made possible using a cell renderer.



Here’s the modified columns array definition.


columns: [
{header: 'Emp No.', width: 100, sortable: true, dataIndex: 'emp_no', align:'center', renderer:  showEmpDetails},
{header: 'Last Name', width: 100, sortable: true, dataIndex: 'last_name'},
{header: 'First Name', width: 100, sortable: true, dataIndex: 'first_name'},
{header: 'Age', width: 75, sortable: true, dataIndex: 'age'},
{header: 'Date of Joining', width: 100, sortable: true, renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'doj'}
]

The renderer function is defined as,

function showEmpDetails(val, meta, rec, rIndex, cIndex, store) {
return "<a href='#'>" + val + "</a>";
//or apply any css class of your choice using
//meta.css = ‘awesome-header-style’
//return val;
}

Here's the JSFiddle -> JSFiddle Row renderer

NOTE: The renderer function should return only ‘html’ content.

Similarly, Rows on the grid can be made to appear in colors other than white/grey.
Consider the employee grid. We could indicate senior employees (age >=27) with a yellow background.





Here’s the modified grid definition,

var grid = new Ext.grid.GridPanel({
store: empStore,
            columns: [
                                {header: 'Emp No.', width: 100, sortable: true, dataIndex: 'emp_no', align:'center', renderer: showEmpDetails},
                                {header: 'Last Name', width: 100, sortable: true, dataIndex: 'last_name'},
                                {header: 'First Name', width: 100, sortable: true, dataIndex: 'first_name'},
                                {header: 'Age', width: 75, sortable: true, dataIndex: 'age'},
                                {header: 'Date of Joining', width: 100, sortable: true, renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'doj'}
                ],
                viewConfig: {
                                //Return CSS class to apply to rows depending upon data values
                                getRowClass: function(record, index) {
                                                var c = record.get('age');
                                                if (c >= 27) {
                                                                return 'senior';
                                                }
                                }
                },
                stripeRows: true,
                height: 350,
                width: 530,
                title: 'Employee Details',
                renderTo: Ext.getBody()
});

The CSS class ‘senior’ is defined as,

<style>
        .senior {
               background-color: #FFFF00
        }

</style> 

Here's the fiddle -> JSFiddle Row renderer

Friday, 28 March 2014

ExtJS grid with numbering & checkbox selection

In this 2nd post I will be enhancing the grid we created in the previous post.
How about adding row numbers to our view? We modify the columns array to hold a new member.

columns: [
new Ext.grid.RowNumberer(),
{id:'company',header: 'Last Name', width: 100, sortable: true, dataIndex: 'last_name'},
{header: 'First Name', width: 100, sortable: true, dataIndex: 'first_name'},
{header: 'Age', width: 75, sortable: true, dataIndex: 'age'},
{header: 'Date of Joining', width: 100, sortable: true, renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'doj'}
]

Here’s the demo,


Here’s the link to the fiddle -> JSFiddle row numbering

By default multiple rows of the grid can be selected by holding down the “Ctrl” button. To disable multi select of rows add the following selection model to the grid.

sm: new Ext.grid.RowSelectionModel({ singleSelect:true })

Selecting multiple rows of a grid can be helpful. But to provide a better visual treatment rather than highlighted rows use a “CheckBoxSelectionModel”.

Here’s the modified grid code,

var sm = new Ext.grid.CheckboxSelectionModel();               
var grid = new Ext.grid.GridPanel({
store: empStore,
columns: [
        sm,   //this is to provide the checkbox for every row
        new Ext.grid.RowNumberer(),
        {header: 'Last Name', width: 100, sortable: true, dataIndex: 'last_name'},
        {header: 'First Name', width: 100, sortable: true, dataIndex: 'first_name'},
        {header: 'Age', width: 75, sortable: true, dataIndex: 'age'},
        {header: 'Date of Joining', width: 100, sortable: true, renderer:        Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'doj'}
],
sm: sm,  //sm is short for “selModel”
stripeRows: true,
height: 350,
width: 430,
title: 'Employee Details',
renderTo: Ext.getBody()
});

Demo below,


Grab the fiddle -> JSFiddle checkbox


Thursday, 27 March 2014

Simple Grid using Ext JS

This blog post assumes you have a little background on Ext JS basics. If not I recommend you to head over to Sencha’s site and have a look at the documentation or even better follow a book.

But this is not rocket science either. A strong foundation in JavaScript is enough to get started.Grid data are very important for the user as most common information display is tabular. Grids or Data grids are made possible by using the class “Ext.grid.GridPanel”.

The following series of blog posts are written following Ext JS version 3.4. Migrating them to the latest version is not hard either. Subsequent posts will improve upon this grid by adding features incrementally. At the end you’ll realize how awesome the framework is.

This is what we will be building by the end of this post.

Let’s start by defining the sample data for the employee database. For the sake of simplicity, lets hardcode our data inside the application.

var empData = [
                       {'last_name':'Doe', 'first_name':'John', 'age':'23', 'doj':'08/06/2009'},
                       {'last_name':'Sparrow', 'first_name':'Jack', 'age':'26', 'doj':'08/12/2010'},
                       {'last_name':'Spacey', 'first_name':'Kevin', 'age':'27', 'doj':'01/23/2011'},
                       {'last_name':'Gates', 'first_name':'Bill', 'age':'35', 'doj':'10/10/2006'}
            ];

Next up we define the store. The store is nothing but a container of records. Each record is nothing but the actual data present in each row.

var empStore = new Ext.data.JsonStore({
                        fields: [
                             {name: 'last_name'},
                             {name: 'first_name'},
                             {name: 'age', type: 'int'},
                             {name: 'doj', type: 'date', dateFormat: 'm/d/Y'}
                         ],
                         data: empData
            });

Next up we define the actual grid,

var grid = new Ext.grid.GridPanel({
store: empStore,
            columns: [
                   {header: 'Last Name', width: 100, sortable: true, dataIndex: 'last_name'},
                   {header: 'First Name', width: 100, sortable: true, dataIndex: 'first_name'},
                   {header: 'Age', width: 75, sortable: true, dataIndex: 'age'},
                   {header: 'Date of Joining', width: 100, sortable: true, renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'doj'}
                ],
             stripeRows: true,
             height: 350,
             width: 400,
             title: 'Employee Details',
             renderTo: Ext.getBody()

});

In the above code,

  1. The “empStore” we just defined is associated with the GridPanel. This connects the store to the actual display grid. Store is not a display component but a behind the scenes prompter. Without it the grid probably does nothing.
  2. We’ve declared the columns for the grid using the columns array. “dataIndex” is the glue which defines the mapping between the record data and the column in which it is supposed to show.
  3. The “renderTo” specifies which DOM elements which would contain this grid. In our case, we chosen the page body.
  4. Setting ‘sortable’ to “false” will disable sorting on that particular column.
  5. Setting ‘stripeRows’ to “false” will not show any difference in row color between consecutive rows.
We're done. Here’s the working fiddle -> JSFiddle ExtJS Simple Grid



Saturday, 16 November 2013

Make your own email app using AngularJS - Part 2

In my previous post, I had started with the basics needed to get an angular application running. Before we add more features let us begin re factoring what we already have.

I've mentioned that our controllers are in the global scope. Let’s fix that.
I am going to assign a value to the ng-app directive. So now when you view the DOM through Firebug, you will notice one global variable which is the app name we assigned to ng-app.

<html ng-app=”emailApp”>

We’re not done here. We need to register emailApp as an angular module for it to work.

Create a new JS file called app.js, with this.

var emailApp = angular.module(‘emailApp’, []);

//we have no dependencies as of now, hence the empty array.

We now need to map our controller(s) to this module. Let’s take this opportunity to migrate the controller code from the html to its own file.


Create a new JS file called controllers.js, with this.

emailApp.controller('EmailCtrl', function($scope) {
                $scope.messages = [{
                                id: 0,
                                sender: 'jean@somecompany.com',
                                subject: 'Hi there, old friend',
                                date: 'Dec 7, 2013 12:32:00'
                }, {
                                id: 1,
                                sender: 'maria@somecompany.com',
                                subject: 'Where did you leave my laptop?',
                                date: 'Dec 7, 2013 8:15:12'
                }, {
                                id: 2,
                                sender: 'bill@somecompany.com',
                                subject: 'Lost python',
                                date: 'Dec 6, 2013 20:35:02'

                }];
});
Now make sure to add app.js and controllers.js to the html page. The screen should come up as before.
There’s no fun in displaying hardcoded data. Let’s ajax-ify it.

To make use of ajax, we need to make use of an ajax service. In angular, services are of 2 types built in and user defined. I will now make use of the built in $http service to make ajax calls. User defined services will be added soon.
Before getting started make sure to move the messages array to a json file. I will save this json as messages.json

The controller now needs to have an extra parameter passed in. That parameter is $http. $http will be injected into our controller by angular. Our controller now looks like this,

emailApp.controller('EmailCtrl', function($scope, $http) {

	$http({method: 'GET', url: 'messages.json'}).

		success(function(data, status, headers, config) {

    		     $scope.messages = data;

  		}).

  		error(function(data, status, headers, config) {

		    console.log("An error occurred. Please refresh.")

		});

});

For these changes to work, we need to run this app using a web server.



Points to note
  • It is recommended to maintain each controller in its own file, rather than using a single controllers.js
  • Most built in services start with the $. It is recommended not to make use of $ for user defined services.
SPA features coming up in part 3.


Saturday, 9 November 2013

Make your own email app using AngularJS - Part 1

     Angular JS is the one of the frameworks I wanted to get started from a long time. Angular, being a product by Google is the reason that got me interested.
So I am going to keep this very simple and write a mail client application. I am not going to lie, I’ve been reading a book on angular. This post is going to be part 1 of “How to build a Gmail killer”. Ha ha. If you find any mistakes, let me know.

To start off, I am going to get started with a simple html page, index.html

What you see below is a standard html5 page. I am dropping angular.min.js and bootstrap.css into the body and head sections respectively. Don’t bother about the file hierarchy for now.  The folks over at Google recommend using Yeoman. Its a long process, so I am going to skip this for now. But worth the effort.

Now the ng-app directive signals angular to kick in at this point. I have placed ng-app on the root node, that is <html>.


Everything else you see on the page is not related to AngularJS. I’ve just added a fancy navbar to our application using Twitter bootstrap.





The screen below shows the actual code for our application. "ng-controller" is assigned a controller name which will manage the div.  Note the usage of “ng-repeat” directive by the <tr> tag.



It’s now time to define EmailCtrl, which is our controller. For now, this controller maintains a hardcoded copy of our email messages.


And that’s it. Open this up and we have our very own email client.



Key points to note:

  • The function “EmailCtrl” is currently defined in the global scope. We’ll rectify that once we start with modules. Also it is recommended to move this script into its own file, say controllers.js.
  • $scope is a very important variable. Look up the Angular docs for a thorough reading. It is injected by the angular framework. Dependency injection brought to you by Angular.
  • The {{ }} are angular’s way to indicate the variable which is bound to a particular tag. So <td>{{ mail.sender }}<td> means that the value of “mail.sender” will be substituted in its place. An alternative to this is this,<td ng-bind=”mail.sender”></td>.
In subsequent posts, I will build upon this example to add SPA features, where we will show a message viewer to view individual emails.
What’s an email client without asynchronous loading? I will bring in ajax support using $http.

Stay tuned.

Thursday, 4 April 2013

Of Typography and web fonts


While coming up with one web page, I thought of using some good fonts to grab attention. So I started weighing my options.
1) You could either choose to host your own system fonts onto your web server. And use this to get it onto your web page

@font-face {
      font-family: "MyAwesomeFont";
      src: url("http://mywebsite.com/MyAwesomeFont.ttf");
}
body {
     font-family: " MyAwesomeFont ", serif
}

But this sounds very old and not trendy enough. We are in the age of clouds and CDN’s. Hosting static content on your server is passé.

2)      The next option is to make use of an online font library. Two big names here, “Typekit” by Adobe and “Google Web Fonts” by elgooG. Typekit being a paid service, I started diving into GWF.
Head over to http://www.google.com/fonts. Choose a couple of fonts you like, review your collection and start using them right away.

There are 3 ways to implement the chosen fonts onto your page.
1)      The standard approach by using <link href=””>
2)      Using @import url()
3)      Using Google WebFont Loader

You can find the actual code snippets for the above 3 methods on google.com/fonts.
After that you can have this(below) to get it working,
body {
     font-family: "MyAwesomeFont1", “MyAwesomeFont2”, Arail, serif
}

Always have a couple of fallback fonts on your font-family declaration. The order in which the fonts are declared here decides which font to use when the preceding font is not found. In this case, it will fall back to a system default serif font if none of the other 3 fonts are found.

The terms serif and sans-serif are not actual fonts as such, but refer to generic font families. This image should help you in case you’ve never heard of serif or sans-serif.



The great Steve Jobs learned typography. You can see that reflecting in the designs that apple has come up with. The i(Mac/ Pod/ Phone) are all built with quality in mind. The same reflects in their UI. Each app that gets published on iTunes undergoes a lot of quality control checks. For more info on these https://developer.apple.com/appstore/guidelines.html

Ok, so I was happy after all these awesome fonts on my page. But then connectivity started breaking down. The fonts were not getting loaded at just the right moment. The result, the browser shows the text initially in a default font and once the font is actually available (downloaded and ready) it swaps the font. What I just witnessed was a FOUT(Flash of Unstyled Text).