EXTJS in XPages #1 – Starting from scratch (the first grid)

In this article I will demonstrate how to create a basic EXTJS grid on your XPages website. I will go through each step of the process and once complete this will be the reference for all following articles on how to do it.

Introduction

EXTJS is a JavaScript library. Well ok to be clear it is MANY JavaScript libraries which can all be added to your XPages in the same way.  I will show you where to find the files, how to add them to your Domino database and then how to use the Extension Library REST service to put your first grid on your XPage.

Sencha

Originally built as an add-on library extension of YUI by Jack Slocum, Ext JS includes interoperability with jQuery and Prototype. Beginning with version 1.1, Ext JS retains no dependencies on external libraries, instead making their use optional.

Licensing

Sencha has two licenses commercial and GPL. For the sake of this blog I am working under the GPL license because everything is being made public. If you want to use the grid for your work you will need to pay for it. A developer pack is $600 each and at a commercial XPages developers charge out rate that is less than a day….I think it will make you more productive!

Downloading

Go to the download page and download the appropriate copy of the whole library (45M-ish).

Getting it into your Database

Once downloaded, unzip the file and get the contents on your machine. That is 210M of unreal goodness and excessive volume and we REALLY don’t need to bloat our database with all that. So delete all the folders except resource and src and remove all the js files until you are left with the extjs files and the license….

ext9

That has got us down to about 30M of files which is still a LOT but they are not going to be loaded into your webpage all at the same time so don’t fret about it

Then drag and drop the root folder into your databases WebContents folder. This can be found in the Package Explorer via  the XPage perspective in 8.5.3 or Window/Show Eclipse Views/Java in <8.5.3.
ext10

Asynchronous Module Definition

As you may know with the dojo libraries there is a methodology called “Asynchronous Module Definition (AMD)” which allows a JavaScript application to load in the modules that it needs – and this rocks! What is also means is that (and I know some of you were thinking it) you are not going to load “30M” worth of files onto your webpage at any time.

Building an XPage

On your XPage you will need to reference the EXTJS library to make sure that is included in your webpage resources. This is done by simply adding the following code to the XPage:

<script type="text/javascript" src="ext-4.1.1/ext-all-debug.js"></script>	
<link href="ext-4.1.1/resources/css/ext-all.css" rel="stylesheet" type="text/css" /> 

This also adds the basic stylesheet to the grid as well (more on that in a later blog post) Once that is added to the XPage then we are all ready to start……

Looking at the examples

As I mentioned in my first article – you really should go look at the examples page in this case specifically the grids section. In there you should poke around and look at the code, terrifying as it may be it really shouldn’t be and as we go through this blog series I will explain and simply all the examples. In this case I am going to look at the RESTful Store example  Clicking on the restful.js link you will see all the code used int his example. I am not going to go into the code itself in this example, suffice as to say you just need to copy and paste 🙂

Creating a grid from a REST service
We are going to start our XPage with Dave Leedy’s fakenames first name view ext1 from that we are going to look at the view in Designer, specifically at the programmatic names of the columns. ext4 As you can see from the image above, each of the columns has a programmatic use name. This is important to remember and necessary to change sometimes.

The REST service.

The REST service is added to an XPage in the following manner – (you must have the Extension Library installed on the client and the server to make this happen). This is the code on my xRestService XPage for the ByFirstName feed. Very simple and sends 100 documents out in JSON format

<xe:restService id="by-FirstName" pathInfo="byFirstName">
	<xe:this.service>
	<xe:viewItemFileService viewName="ByName-First"
		count="100" defaultColumns="true" systemColumns="132">
	</xe:viewItemFileService>
	</xe:this.service>
</xe:restService>

Looking at the REST service through a URL call we see the following format for the output:

{
    "@timestamp":"2013-02-23T06:53:34Z",
    "@toplevelentries":1300,
    "items":
    [
      {
          "@entryid":"1-66F3A5FE2B2A38CC85257B1B00254E6D",
          "@unid":"66F3A5FE2B2A38CC85257B1B00254E6D",
          "@noteid":"688E",
          "@position":"1",
          "@siblings":1298,
          "firstname":"Adam",
          "lastname":"Saenz",
          "address":"2519 Custer Street",
          "city":"ROCKWOOD (SOMERSET)",
          "state":"PA",
          "zip":15557,
          and so on,
      },
      {
          "@entryid":"2-3857882D6726A78F85257B1B00254F1C",
          "@unid":"3857882D6726A78F85257B1B00254F1C",
          "@noteid":"6B4A",
          "@position":"2",
          and so on,

Adding the Grid to the XPage I have simplified the example given on the Sencha site so that we can just see the bare bones of the grid. As we go through th series I will add more and more complication into the grids so that we can see how they work. The grid code is built up of multiple components:

  • Require the necessary EXTJS libraries
  • Defining a People Object
  • Creating the data store
  • Getting the grid data from the REST service
  • Applying the data to the grid in columns

So let’s look at the code The AMD part

Ext.require(['Ext.data.*', 'Ext.grid.*']);

The Person Object In here we define the fields ‘firstname’, ‘lastname’, ‘address’, ‘city’, ‘state’. These field names relate to the names of the fields coming in through the REST service JSON string and therefore directly to the programmatic column name in the view (told you it was important)

Ext.define('Person', {
    extend: 'Ext.data.Model',
    fields: [{
         'firstname', 'lastname', 'address', 'city', 'state']
});

The Data Store In this section the data Store is created which is used to populate the grid. The store: defines the Person Object (above) as the model to display the information sets up the connection to get the REST service from the ‘xRestService.xsp/byFirstName’ URL

    var store = Ext.create('Ext.data.Store', {
        autoLoad: true,
        autoSync: true,
        model: 'Person',
        proxy: {
            type: 'rest',
            url: 'xRestService.xsp/byFirstName',
            reader: {
                type: 'json',
                root: 'items'
            },
            writer: {
                type: 'json'
            }
        }
    });

The Grid itself Finally we build the grid – and the grid parameters define what it looks like – I have added comments to the code so that you can see in place what each section is doing

    var grid = Ext.create('Ext.grid.Panel', {
        renderTo: 'gridHere',		//render to the id named gridHere
        width: 600,			//width of the grid
        height: 300,			//height of the grid
        frame: true,
        title: 'Users',			//Grid title at the top
        store: store,			//Store object
        iconCls: 'icon-user',		//icon for the title
        columns: [{			//for each column in the grid define the attributes of the column
            header: 'First',		//Column Header Title
            width: 80,			//Column width
            sortable: true,		//Is the column sortable?
            dataIndex: 'firstname',	//what is the data field in the JSON used to fill this column
            field: {			//what type of field is this?
                xtype: 'textfield'
            }
        }, {
            text: 'Last',
            width: 80,
            sortable: true,
            dataIndex: 'lastname',
            field: {
                xtype: 'textfield'
            }
        }, {
            text: 'Address',
            width: 80,
            sortable: true,
            dataIndex: 'address',
            field: {
                xtype: 'textfield'
            }
        }, {
            text: 'City',
            width: 80,
            sortable: true,
            dataIndex: 'city',
            field: {
                xtype: 'textfield'
            }
        },{
            text: 'State',
            width: 80,
            sortable: true,
            dataIndex: 'state',
            field: {
                xtype: 'textfield'
            }
        }]
    });
});

And there it is – you add all the above in a SCRIPT tag on the XPage the code for you first grid. We also add a little CSS to show the icon for the image and a div as a container. This is not the “best” way to do it, and we will discuss that in a later article but for the moment it is the easiest to understand being in the same XPage.

<script type="text/javascript" src="ext-4.1.1/ext-all-debug.js"></script>
	<link href="ext-4.1.1/resources/css/ext-all.css" rel="stylesheet" type="text/css" /></pre>
<style><!--
.icon-user {
    background-image: url(images/user.png) !important;
}

.icon-add {
    background-image: url(images/add.png) !important;
}

.icon-delete {
    background-image: url(images/delete.png) !important;
}
--></style>
<pre>
<script type="text/javascript">// <![CDATA[
Ext.require(['Ext.data.*', 'Ext.grid.*']);

Ext.define('Person', {
    extend: 'Ext.data.Model',
    fields: [{
        name: 'id',
        type: 'int',
        useNull: true
    },  'firstname', 'lastname', 'address', 'city', 'state']
});

Ext.onReady(function(){

    var store = Ext.create('Ext.data.Store', {
        autoLoad: true,
        autoSync: true,
        model: 'Person',
        proxy: {
            type: 'rest',
            url: 'xRestService.xsp/byFirstName',
            reader: {
                type: 'json',
                root: 'items'
            },
            writer: {
                type: 'json'
            }
        }
    });

    var grid = Ext.create('Ext.grid.Panel', {
        renderTo: 'gridHere',
        width: 600,
        height: 300,
        frame: true,
        title: 'Users',
        store: store,
        iconCls: 'icon-user',
        columns: [{
            header: 'First',
            width: 80,
            sortable: true,
            dataIndex: 'firstname',
            field: {
                xtype: 'textfield'
            }
        }, {
            text: 'Last',
            width: 80,
            sortable: true,
            dataIndex: 'lastname',
            field: {
                xtype: 'textfield'
            }
        }, {
            text: 'Address',
            width: 80,
            sortable: true,
            dataIndex: 'address',
            field: {
                xtype: 'textfield'
            }
        }, {
            text: 'City',
            width: 80,
            sortable: true,
            dataIndex: 'city',
            field: {
                xtype: 'textfield'
            }
        },{
            text: 'State',
            width: 80,
            sortable: true,
            dataIndex: 'state',
            field: {
                xtype: 'textfield'
            }
        }]
    });
});
// ]]></script></pre>
<div id="gridHere"></div>
<pre>

ext5

Demonstration

The EXTJS in XPages demonstration database can be found at http://demo.xomino.com/xomino/extjs.nsf

You will note that the menu does not look right – I know – one thing to discuss with the grids – their stylesheets…..we will see 🙂

This was tested in IE9, Safari, Chrome, Firefox, Chrome on Android and iPhone/iPad

Play with the columns and see what they can do – I will post again soon to discuss the capabilities of the basic grid further.

Download

The sample database that will accompany this series will always be available from the menu in the live demo database from this link – http://demo.xomino.com/xomino/Extjs.nsf

Conclusion

I think it is safe to say that this is a simple, fantastic, aesthetically pleasing, way of showing data on the screen to the users and hopefully this was a simple enough process to follow along with. This is a simple grid with not much functionality but as we will come to see – there are w whole world of different capabilities within the EXT grids and their plugins 🙂

13 thoughts on “EXTJS in XPages #1 – Starting from scratch (the first grid)

  1. Great intro to Ext JS grids. Just a couple of corrections for you though. The ‘field’ properties in the column objects aren’t needed in your example since those are only used for the editing plugins which you aren’t using. Also, since you’ve stripped the example down to not include the editor plugin or the code to add/remove records to the store then you don’t really need to use a ‘rest’ proxy. You can use an ‘ajax’ proxy instead. Otherwise, great job! I’ve been using Ext JS with Domino for over 6 years and love it and its great to finally hear more and more developers discovering this awesome framework.

    • Jack, thank you so much for the comments. I know I still have a lot to learn and I really appreciate your input and help 🙂

      • oh, no problem. I have lots of experience and knowledge working with Ext JS and Domino but I’m pretty new to XPages so I have a lot to learn in that area and so I’m really enjoying these posts you are putting out. 🙂

  2. Mark, the code for how you set up the REST services is missing from the blog entry, though it is in the example db. Working through this today to see if I can follow along and put it to use right away. As I mentioned, I sat down to figure this out starting on the weekend and, knowing you’d written but not yet published today’s post, I held off on attempting to put it to use. Hopefully, I can expand on your work….

    • thanks David – way too many things wrong with the wordpress editor this morning – I think I got them resolved

      thanks to Brad as well who pointed this out last night and I thought I had fixed it then…..

  3. On my machine, in IE8, only the top dozen pixel rows of the grid display. I thought it was something with the implementation I was trying, but it fails the same way in the demo. I normally do everything in Firefox and only test against IE, but I was being lazy and kept running it in IE from DDE and wondering what I’d done wrong. IE8 just doesn’t like it for some reason.

  4. This design is wicked! You most certainly know how
    to keep a reader entertained. Between your wit and your videos, I was almost moved
    to start my own blog (well, almost…HaHa!) Great job.
    I really loved what you had to say, and more than that, how you
    presented it. Too cool!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s