EXTJS in XPages #8 – Selecting data from the grid and opening a document

In this article I will show you how to get data upon selecting a document – I will then demonstrate how we open a document from the grid.

EXTJS in XPages series

Here are links to all of the previous articles in this series

Demonstration

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

Download

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

Selection Model

The selection model for a grid is very easily retrieved using the dblclick event within the grid:

 var selection =  grid.getSelectionModel().getSelection();
 var fieldValue = selection[0].data.fieldname

Listeners

To detect the double click event we have to add a listener to the grid. There are many listeners for the grid and more information on them can be found here in the Sencha help files

grid = Ext.create('Ext.grid.Panel', {
	listeners: {      //listener config setting for the grid
		events HERE.....................
	}
}

Getting the UNID

In out view we are going to add a  new column docid – very simple @Text(@DocumentUniqueID) column formula. But this column is not going to be displayed in the view – it is going to be hidden.

We add the new column and add the “hidden: true” property to it in the grid so that it is not visible to the user. But this does mean that it is available to us programmatically.

{
	text: 'docid',
	width: 10,
	dataIndex: 'docid',
	hidden: true
},

(Note: the @UNID property is passed in by the REST service and *yes* we could use that instead of adding a new column – however I feel that this is easier to explain and does not require a discussion regarding the usage of a property of the REST service JSON array )

Opening the document

In our example grid we are simply going to open our document by getting the docid field from the hidden column and opening a window using a manually generated URL string

So all together or grid code now looks like this:

grid = Ext.create('Ext.grid.Panel', {
	renderTo: 'gridHere',
	frame: true,
	features: [filters],
	height: 400,
	title: 'Users',
	store: store,
	iconCls: 'icon-user',
	listeners: {      //listener config setting for the grid
		itemdblclick: function(dataview, record, item, index, e) {
			console.log('dblClick Event')
			var selection = grid.getSelectionModel().getSelection()
			window.open('xPerson.xsp?action=readDocument&documentId='+selection[0].data.docid)
		}
	}
}

As you can see from the example page this is simple, effective and completely poor as a user experience – but this article was about getting data from the grid – not about making a cool application 🙂

Conclusion

Programmatically accessing data in the grid is a very powerful technique when attempting to manipulate the EXTJS grids and insert them into your application.

EXTJS in XPages #7 – Doing an @Unique(@DbColumn) equivalent in the grid

In this article I will show you how to make a simple @Unique(@DbColumn)) equivalent in the EXTJS grid

Introduction

When you have a notes view/EXTJS grid you often want to be able to do a lookup of all the unique values in a column – this is especially useful when you are also applying filters in the grid.

What is particularly useful is that the values in the column are uniqued automatically – this allows you to reduce down the values which are presented to the user to select from. This also means not having to create some elaborate search/filter capability going back to the server to change the lookup.

Caveat

This only works on the data in the current view so will not work if you are using remote filtering. In a later article I will demonstrate the new 4.2 BufferedRenderer which makes front end filtering on 10,000 documents a reality

The code

The code is very simple and can be demonstrated easily by adding a ComboBox to the grid – in this example the combobox is appended to the grid and the values come from the state field in the grid store

new Ext.form.ComboBox({
        renderTo: 'gridHere',
        store: grid.getStore().collect('state')
    });

ext1

Filtering the grid reduces the data

ext2

and then running the add combobox again now creates one with a reduced set – NOT the uniquing of the values automatically

ext3

To see the returned value we just use firebug and execute the collect method – you can see that the values are returned as an array – this could then be parsed into any field.

ext4

Conclusion

Using the EXTJS grid can be very much akin to using a notes view – the trick is having the knowledge to know what is possible.

PS

The data is returned in the order that it is presented in the grid – if you want alphabetically then so an array.sort()

🙂

Searching XPages REST service and returning the real count in the results.

In this article I will show you how I managed to get the search results count into a REST service and why I wanted to do that.

Introduction

Back in August 2012 I posted this on Stackoverflow. I will answer the question there but I don’t feel like I have “answered” it, just worked around it.

How do I make the XPages REST control return the overall number of filtered matches?

http://stackoverflow.com/questions/11786930/how-do-i-make-the-xpages-rest-control-return-the-overall-number-of-filtered-matc

Problem

When you create a viewItemFileService REST service using the the ExtensionLibrary control you get a response which looks like this:

{
    "@timestamp":"2013-03-12T23:25:57Z",
    "@toplevelentries":1299,
    "items":
    [
      {
          "@entryid":"100-8DE5EBF5E35C17F285257B1B00254A8F",
          "@unid":"8DE5EBF5E35C17F285257B1B00254A8F",
          "firstname":"Benjamin",
          "lastname":"Imran",
          "address":"2112 Hall Street",
          "city":"Las Vegas",
          "state":"NV",
          "zip":89121,
          "country":"US",
          "email":"Benjamin.A.Wayman@mailinator.com"
      },

which is fine…and from that you can ascertain that there are 1299 documents in the view (@toplevelentries)

The problem is when you execute a search against this REST service (for example ‘[address] contains street’) you still get @toplevelentries: 1299

This causes me great angst when it comes to the EXTJS grids because I want to use the Infinite Scrolling capability. What that does is calculates based on the size of the view (1299) how large a scroll bar to create and then display 25 entries at a time and load them as necessary. This is really smart except after you have searched the REST service. The grid still thinks there are 1299 documents even when there is only a subset matching the search results. This causes a lot of blank scrolling 😦

In my example the search ‘[address] contains street’ returns 338 matches. But this causes the following to happen with the infinite grid

rest1

And that sucks. Also note 52 pages in the pager!!!!

The EXTJS code to get the number of documents in the service looks like this:

 var store = Ext.create('Ext.data.Store', {
        // allow the grid to interact with the paging scroller by buffering
        buffered: true,
        pageSize: 25,
        leadingBufferZone: 25,
        autoLoad: true,
        autoDestroy: true,
        autoSync: true,
        model: 'Person',
        proxy: {
            type: 'rest',
            url: 'xRestService3.xsp/marky?count=25',
            reader: {
                type: 'json',
                root: 'items',
                totalProperty : '@toplevelentries' // This is the determining value
            },
            writer: {
                type: 'json'
            }
        }
    });

And as you can see form the code @toplevelentries is always 1299

So how do we get the 338 number to the grid without causing:

  • Some major hacktastic, back end to front end, extra ajax calls, and  redrawing the grid on the fly shenanigans
  • Manually re-writting the REST service from scratch (which I could do but would cause much pain and suffering)
  • Performance issues with XPiNC connecting to the server
  • My eyes to bleed…..

This has baffled me for months and here’s how I got around it.

Solution

In the REST service you can create a custom column. In this case we are just returning the requestScope value for markyCount in the column “theRealCount”:

<xe:this.columns>
	<xe:restViewColumn name="theRealCount">
		<xe:this.value>
		<![CDATA[#{javascript: return requestScope.get("markyCount")}]]>
		</xe:this.value>
	</xe:restViewColumn>
</xe:this.columns>

And markyCount is going to be the 338 value from the search. So how do we get that?

The REST service has an id value which can be computed – and I really don’t care what the id is because I am not binding it to a control on the form. So I used the opportunity for some server side computation of the id to create a little FTSearch.

In the example below I am simply getting the view used by the REST service (byFirstName) doing an FTsearch on it and then putting the count in the markyCount requestScope.

<xe:this.id>
	<![CDATA[${javascript:
		var theView:NotesView = database.getView("byFirstName")
		var count = theView.FTSearch("[address] contains street");
		requestScope.put("markyCount", count)
		return "searchMe" //irrelevant value
		}
	]]>
</xe:this.id>

So what this does is create a REST service output which looks like this:

{
    "@timestamp":"2013-03-12T23:25:57Z",
    "@toplevelentries":1299,
    "items":
    [
      {
          "@entryid":"100-8DE5EBF5E35C17F285257B1B00254A8F",
          "@unid":"8DE5EBF5E35C17F285257B1B00254A8F",
          "firstname":"Benjamin",
          "lastname":"Imran",
          "address":"2112 Hall Street",
          "city":"Las Vegas",
          "state":"NV",
          "zip":89121,
          "country":"US",
          "email":"Benjamin.A.Wayman@mailinator.com",
          "theRealCount": 338  //this is the new column
      },

Note theRealCount column with 338 in it. This is then added to every column output by the REST service. So yes the downside is that we are adding computation and output data size to the feed but it appears to make an insignificant amount of difference to the output speed of the service.

We then change the EXTJS code to look at the theRealCount value in the first Item and not @toplevelentries

 var store = Ext.create('Ext.data.Store', {
        // allow the grid to interact with the paging scroller by buffering
        buffered: true,
        pageSize: 25,
        leadingBufferZone: 25,
        autoLoad: true,
        autoDestroy: true,
        autoSync: true,
        model: 'Person',
        proxy: {
            type: 'rest',
            url: 'xRestService3.xsp/marky?count=25',
            reader: {
                type: 'json',
                root: 'items',
                totalProperty : 'items[0].theRealCount' // This is the determining value
            },
            writer: {
                type: 'json'
            }
        }
    });

And we get this – no more blank lines and 14 pages in the pager 🙂

rest2

EXTJS in XPages #5 – Infinite scroller

In this article I will show how simple it is to turn your paging grid into an infinite scrolling one.

EXTJS in XPages series

Here are links to all of the previous articles in this series

Demonstration

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

Download

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

Introduction
In the last article I show how to add a pager to your grid to prevent a significant number of documents from loading into your grid at once. This is more analogous to the view panel out of the box paging that we are familiar with in the XPages environment.

From a user interaction perspective paging is good and allows the user to sort through each 25 documents worth of data. But it fails miserably when you have to page more then 4 times to get more data. That task of having to page down through the data becomes very cumbersome very quickly.

Infinite scrolling

The concept of infinite scrolling was first made popular on websites like Facebook and Twitter. When the user gets to the bottom of the screen an icon appears indicating more data loading and then the user continues to scroll. This has now become the expectation of users trying to sift through a lot of data on the web.

Add in infinite scrolling to your grid

Adding infinite scrolling is as simple as 3 lines of additional code in your existing grid. This feature is only supported as of EXTJS 4.1 only.

1. We require the paging scroller library to be loaded
2. We add a line to the grid signifying that this is a buffered data set
3. We Did another parameter to allow a “scroll ahead” before the next data set is loaded.

Looking at the video below you can see that as the user starts to scroll the page seems to just go and go – and only when dragging the scroll bar down quickly do you even see a Loading Mask. Adding Firebug console you can see that the buffered pages are loaded into memory before the user gets to the point of the grid where they would need to be displayed.

Here is the code sections which have changed since the last article.


Ext.require([
       	'Ext.data.*',
       	'Ext.grid.*',
        'Ext.toolbar.Paging',
        'Ext.grid.PagingScroller'       //THIS LINE
]);

var store = Ext.create('Ext.data.Store', {
    // allow the grid to interact with the paging scroller by buffering
    pageSize: 25,
    buffered: true,               //THIS LINE
    leadingBufferZone: 25,        //THIS LINE
    autoLoad: true,
    autoDestroy: true,
    autoSync: true,
    model: 'Person',
    proxy: {
        type: 'rest',
            url: 'xRestService.xsp/byFirstName?count=25',
            reader: {
                type: 'json',
                root: 'items',
                totalProperty : '@toplevelentries'
            },
            writer: {
                type: 'json'
            }
        }
    });

Performance

This is a huge performance boost from loading all the documents into the grid at once. When using the grid purely as a reporting display model, you should consider using the infinite scrolling capabilities of the grid as a standard. There are some caveats though to be aware of; when it comes to interactivity with the grid data this can cause some challenges (see below)

This performance boost is most significant in IE and XPiNC where a few hundred documents can slow down the browser. With infinite scrolling you can have 10,000 documents in a view and scroll to any of them.

Better than Paging?

Absolutely:

  • A familiar interface for users experienced in using the notes client
  • A much faster way to find the user to find the page containing their document of reference.
  • Less bandwidth wasted guessing. Moving the scroll bar up and down to a visual guide is more accurate than guessing the number of the page where the document might be based on the sorting of the column in question.

What about filtering?

Infinite scrolling does have a couple of downsides if you want to use other parts of the grid functionality. Because you are only showing a few of the documents at a time – filtering the “loaded documents” is not going to give you anything and you have to go with remote filtering. Remote filtering is quite possible in the XPage environment but I am unable to share at this time as it was part of a client engagement where we implemented this.

What about sorting?

Also with sorting you can sort the local documents in the grid – but that doesn’t really help. You have to use remote sorting which can be done and we will look at in the next article.

Custom Control

Adding infinite scrolling to the custom control is easy because the only things which have changed are the 3 lines of Javascript. This has been updated in the demo database.

Conclusion

Paging is better than loading all documents into the grid at once. Infinite scrolling is better than Paging in most cases. Like everything in this series, there are pros and cons which have to be considered for each piece of functionality and it is important to understand them so that you can verbalize these considerations to your customer when architecting a solution.

EXTJS in XPages #4 – Adding a Pager

In this article I will demonstrate how to add a pager control to your basic grid.

Demonstration

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

Download

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

Introduction

As we saw from the previous articles we can make a basic EXTJ grid from a REST service. Loading a huge number of documents into an EXTJS grid does have its drawbacks though:

  • Poor user experience to have to search down through hundreds of records
  • Browser memory management issues.

Too many documents? *Warning*

Unlike traditional notes which allows for a personal cache of data for the user through the notes client, the web browser is not capable of doing this. Any browser (some worse than others) is going to run into problems when you load a significant amount of data on a page. In my experience the worst browser for this is the XPiNC browser (Firefox 3.5 code base), then IE then Firefox and Chrome.

As the developer you also have to consider:

  • load time
    • how long will it take to load hundres of documents from the REST service over your network
  • parsing time for the grid library
    • The EXTJS code has to take the JSON and create from it a gigantic table and add that to the DOM. This takes time and browser resources – too slow and the user gets impatient.

Recommendation

If you have more than 250 documents do not load them all into the grid at any one time. For all of the reasons above, starting with the user experience. While Notes Client or Excel may be able to allow a user to manage thousands of records, a web browser is not – find a better way.

Adding a Paging toolbar

There are only a couple of steps to adding a paging toolbar to the bottom of your grid.

First we need to add a property to the store – so that the grid knows how many documents are coming in

   var store = Ext.create('Ext.data.Store', {
        autoLoad: true,
        autoDestroy: true,
        autoSync: true,
        model: 'Person',
        proxy: {
            type: 'rest',
            url: 'xRestService.xsp/byFirstName?count=25',    // ?count=25 sets the number of docs the REST sends each time
            reader: {
                type: 'json',
                root: 'items',
                totalProperty : '@toplevelentries'     //This comes from the REST service
            },
            writer: {
                type: 'json'
            }
        }
    });

The REST service provides the @TopLevelEntries – this is the number of documents in the view


{
    "@timestamp":"2013-03-02T16:09:08Z",
    "@toplevelentries":1299,  // <----------
    "items":
    [
      {
          "@entryid":"1-66F3A5FE2B2A38CC85257B1B00254E6D",
          "@position":"1",
          "firstname":"Adam",
          "lastname":"Saenz",
          "address":"2519 Custer Street",
          "city":"ROCKWOOD (SOMERSET)",
          etc etc,

We then need to add the code to the EXT.require to include the Paging toolbar

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

and finally add the toolbar to the grid itself by adding it as a property after the columns

        // paging bar on the bottom
        bbar: Ext.create('Ext.PagingToolbar', {
            store: store,
            displayInfo: true,
            displayMsg: 'Displaying topics {0} - {1} of {2}',
            emptyMsg: "No topics to display"
        })

And that’s it.

ext41

The 1 of 52 is calculated by the grid 1299 documents divided by 25 documents at a time = 52 pages

Custom Control update

We can add the pager to the XPages Custom Control in the same way as previously described in the last article – but in the case we need to add another property – how many documents per page instead of how many documents for the overall feed.

        proxy: {
		            type: 'rest',
		            url: '#{javascript:facesContext.getExternalContext().getRequest().getRequestURI()+"/ccREST?count="+compositeData.countNum}',
		            reader: {
		                type: 'json',
		                root: 'items',
		                totalProperty : '@toplevelentries'
		            },
<xe:restService pathInfo="ccREST" id="restServe1" >
	<xe:this.service>
		<xe:viewItemFileService  defaultColumns="true" viewName="${javascript:compositeData.theViewName}"></xe:viewItemFileService>
	</xe:this.service>
</xe:restService>

ext42

In this case you can see we are using the whole ByFirstName view and the generic Custom Control displayed all the columns successfully !

This Custom Control is available in the download database (ccEXTJSGridwithPager)

EXTJS in XPages #3 – Creating a basic grid from a Custom Control

In this article I will demonstrate how to create an EXTJS grid representation of a view using a custom control and 3 custom properties. At the end of this article you will be able to drag and drop a custom control onto your XPage, give it the count, the viewName and the name of the placement element and a grid will be created for you without any further coding.

Introduction

In XPages we want to be able to genericize everything down to a re-usable custom control and in this example I will show you how to add a grid to your XPage doing just that. The following XPage source code is all that is needed to create this basic grid capability.

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" xmlns:xc="http://www.ibm.com/xsp/custom">

	<xc:ccBasicExtJSGrid countNum="10" putGridHere="gridHere" theViewName="ByName-First5Col" ></xc:ccBasicExtJSGrid>

	<div id="gridHere" class="extjsGrid"></div>

</xp:view>

Demonstration

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

Download

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

The Custom Control

The Custom Control is created with 3 Properties which are populated when it is added to the XPage. You add it to your XPage by dragging and dropping and adding the 3 properties:

xt31

The View

The view ByName-First5Col is a simple view of 5 columns containing a single field in each column but as we will see this control will handle any number of columns.

ext32

The code

The end result is to create the JavaScript necessary to create a Basic grid in the same fashion as I did in the first article. But in this case we are not providing the column names or headers, we are programmatically getting them from the view itself.

The fields are created by going to the view and getting the columns and then of those, the item name (nvc.getItemName())

var fields=[
		#{javascript:
				var view:NotesView = database.getView(compositeData.theViewName)	//get the view
				var msg=[];
				for (var i=1; i<view.getColumnCount()+1; i++){
					var nvc:NotesViewColumn = view.getColumn(i);			//get each view column in turn
					msg.push('\''+nvc.getItemName()+'\'')				//get the column programmatic name
				}
				return msg.join(',')							//return the string of fields
		}
	]

The columns are created in the same maner but instead of getting just the column Item Name we get the column Title (nvc.getTitle() as well)

var columns=[
	#{javascript:
			var view:NotesView = database.getView(compositeData.theViewName)
			var msg=[];
			for (var i=1; i<view.getColumnCount()+1; i++){
				var nvc:NotesViewColumn = view.getColumn(i);
				//Create the JSON object containing the column programmatic name and the column title form the view
				msg.push('{header: \''+nvc.getTitle()+'\', sortable: true, dataIndex: \''+nvc.getItemName()+'\'}')
			}
			return msg.join(',')
		}
	]

I added the REST control to the Custom Control itself for simplicity and to make it more portable. This does have the restriction (at this time) of only having one grid on a page at a time. The pathInfo and id of a REST control cannot apparently be computed at build time so I have to keep them static. I am sure there is a way around it…in the mean time the viewName is passed in via compositeData as well as the count. As I think about it you could probably give control to the user using scoped variables and have them select the number of documents displayed…but that is for later.

	<xe:restService pathInfo="ccREST" id="restServe1" >
		<xe:this.service>
			<xe:viewJsonService defaultColumns="true" count="${javascript:compositeData.countNum}" viewName="${javascript:compositeData.theViewName}"></xe:viewJsonService>
		</xe:this.service>
	</xe:restService>

The viewName is also passed into the EXTJS code so that it knows where to look for the REST service on the page.

    var store = Ext.create('Ext.data.Store', {
        autoLoad: true,
        autoDestroy: true,
        autoSync: true,
        model: 'Person',
        proxy: {
            type: 'rest',
            url: '#{javascript:facesContext.getExternalContext().getRequest().getRequestURI()+"/ccREST"}',
            reader: {
                type: 'json',
                root: 'items'
            },
            writer: {
                type: 'json'
            }
        }
    });

The EXTJS code is then simplified because we are passing in the fields and columns values already computed above. Below is the code for the whole Custom Control.

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" xmlns:xe="http://www.ibm.com/xsp/coreex">
	<script type="text/javascript" src="ext-4.1.1/ext-all.js"></script>
	<link rel="stylesheet" type="text/css" href="ext-4.1.1/resources/css/ext-all.css" />

	<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>

	<xp:scriptBlock id="scriptBlock1">
		<xp:this.value><![CDATA[

		var fields=[
			#{javascript:
					var view:NotesView = database.getView(compositeData.theViewName)
					var msg=[];
					for (var i=1; i<view.getColumnCount()+1; i++){
						var nvc:NotesViewColumn = view.getColumn(i);
						msg.push('\''+nvc.getItemName()+'\'')
					}
					return msg.join(',')
			}
		]

		columns=[
			#{javascript:
					var view:NotesView = database.getView(compositeData.theViewName)
					var msg=[];
					for (var i=1; i<view.getColumnCount()+1; i++){
						var nvc:NotesViewColumn = view.getColumn(i);
						msg.push('{header: \''+nvc.getTitle()+'\', sortable: true, dataIndex: \''+nvc.getItemName()+'\'}')
					}
					return msg.join(',')
				}
			]

		Ext.Loader.setConfig({
		  enabled : true,
		  disableCaching : false
		});

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

		Ext.define('Person', {
		    extend: 'Ext.data.Model',
		     fields: fields
		});

		Ext.onReady(function(){

		    var store = Ext.create('Ext.data.Store', {
		        autoLoad: true,
		        autoDestroy: true,
		        autoSync: true,
		        model: 'Person',
		        proxy: {
		            type: 'rest',
		            url: '#{javascript:facesContext.getExternalContext().getRequest().getRequestURI()+"/ccREST"}',
		            reader: {
		                type: 'json',
		                root: 'items'
		            },
		            writer: {
		                type: 'json'
		            }
		        }
		    });

		    var local = true;

		     var filters = {
		        ftype: 'filters',
		        // encode and local configuration options defined previously for easier reuse
		        //encode: encode, // json encode the filter query
		        local: local   // defaults to false (remote filtering)

			};

		    var grid = Ext.create('Ext.grid.Panel', {
		        renderTo: 'gridHere',
		        frame: true,
		        features: [filters],
		        height: 400,
		        title: 'Users',
		        store: store,
		        iconCls: 'icon-user',
		        columns: columns
		    });
		});
			]]></xp:this.value>
	</xp:scriptBlock>

	<xe:restService pathInfo="ccREST" id="restServe1" >
		<xe:this.service>
			<xe:viewJsonService defaultColumns="true" count="${javascript:compositeData.countNum}" viewName="${javascript:compositeData.theViewName}"></xe:viewJsonService>
		</xe:this.service>
	</xe:restService>
</xp:view>

Results

As you can see below – a grid, same as we had before.

extjs33

But now we can add a new column to view and without changing the control itself the new column appears on the web.


ext34

ext35

And even complex columns with combined field values.

ext37 ext36

Conclusions

With this Custom control we are able to begin to create the ability to add these EXTJS grids to our XPages, very quickly and very effectively. As we go through the series I will update the custom control with the new capabilities as we look at new grids. Eventually we will have a plethora of controls which can be used to create powerful grids in next to no time at all.

In the mean time you can download the control from the sample database and play with it yourself. http://demo.xomino.com/xomino/Extjs.nsf

EXTJS in XPages #2 – Basic Grid capabilities

In this article I will demonstrate the basic out of the box functionality which comes with each grid and will focus on the capabilities of each column.

Introduction

In the previous article I demonstrated how to add a basic grid to your XPage using the EXTJS grid control and the ExtLib REST service. What we will look at in this article is the basic capabilities of the view columns.

Re-sizing columns

If you mouse over a column separator at the top you will see a familiar icon – clicking on the separator you can drag and drop the column increasing and decreasing the size

ext11 ext12 ext13

Re-ordering of columns

If you click on a column and “drag it” over to the left and right you can re-order them.

ext21

ext22

ext23

Hiding columns

If you mouse over the top right of a column you will see a drop down icon appear – click on it and you will be able to hide one of the columns. You can actually programmatically hide the columns when the grids open and have the users make them visible later if you want to.

ext25

ext26

Sorting Columns

If you click on the column header – or click on the small drop down and select to order the column you can do that

ext24

Filtering Columns

Well ok this is not a BASIC feature of the grid as it is added as another required library – but I figured I would show it cos it is COOL and should be a basic premise of the grids you create. Code will be provided in a later article but for now just know that it can be done locally (filtering the grid contents) and remotely (asking the server for a filtered results set) and it is in the basic demo site


ext6ext7ext8

Demonstration

Go look at the basic demo site and see for yourself.