Ask a Jedi: Removing Pagination from CFGRID

This post is more than 2 years old.

Nathan asks:

I am recently getting into CF8 and Ajax features and for doing so building a small application to add items to a cart. I have it setup currently that items are in a select box and a cfgrid shows some item information of the item selected. Since, at a time only one item can be selected, I want to remove the pagination that comes by default with cfgrid. I am able to do that if I get a result query and use the cfgrid with a query attribute, but if I go for a dynamic bind, the pagination controls are present.

This was an interesting problem. First, let's be sure we are clear on what Nathan is seeing. The sexy new CFGRID added in ColdFusion 8 allows you to either directly pass a query to the grid itself (with a query defined on the same page, or loaded via CFC, UDF, etc) or load it via Ajax. This is done with the bind attribute.

If you pass the query to the grid then the pagination controls are not displayed. For example:

Even if you set a pagesize attribute, it will be ignored and the entire query will be displayed in the grid. Now compare this a grid that loads it's data via the bind attribute:

So how do you get rid of the bar? I knew that ColdFusion provided a function, ColdFusion.Grid.getGridObject, that would give me direct access to the grid. I figured then it would be a simple matter of checking the Ext API docs to see if there was a method to hide the panel.

I dug... and I dug... but I was unable to find anything that made sense to me. Using Firebug and the console.dir command (think of it as a ColdFusion dump), I finally found this:

var myGrid = ColdFusion.Grid.getGridObject('entries'); myGrid.view.getFooterPanel().setVisible(false); myGrid.view.refresh();

This seemed to work well. I then added an ajaxOnLoad() call to run the code on load. Here is the complete example:

<html>

<head> <script> function testit() { var myGrid = ColdFusion.Grid.getGridObject('entries'); myGrid.view.getFooterPanel().setVisible(false); myGrid.view.refresh(); } </script> </head>

<body>

<cfform name="test"> <cfgrid autowidth="true" name="entries" format="html" width="600" bind="url:getentries.cfm?page={cfgridpage}&pagesize={cfgridpagesize}&sort={cfgridsortcolumn}&dir={cfgridsortdirection}"> <cfgridcolumn name="id" display="false"> <cfgridcolumn name="body" display="false">

<cfgridcolumn name="title" header="Title"> <cfgridcolumn name="posted" header="Posted"> </cfgrid> </cfform> <cfset ajaxOnLoad("testit")>

</body> </html>

I'm not sure this is the best way to do it (I've actually got an Ext book on the way to me for review purposes), but it seems to work ok. Another solution would have been to use the drop down to drive a bound cfdiv tag. That cfdiv then could have loaded both an inline query and cfgrid.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Nate posted on 12/22/2008 at 9:09 PM

Thanks for the post Ray. This is what I was looking for.

I am surprised that Adobe did not include some of these simpler options in their CF tags for use and that we have to dig into ExtJS to use them. There is an additional issue here that the grid look will change after the page has loaded (correct me here if I am wrong).

The advantage of using cfgrid with bind instead of using a cfdiv with an inline query and cfgrid is that cfdiv always shows the "loading graphic" whenever the select box is changed, while cfgrid with bind is much more dynamic. But the cfdiv solution sounds more pleasing to me right now than modifying the grid after it has loaded.

Comment 2 by Raymond Camden posted on 12/22/2008 at 9:10 PM

I think Adobe made some educated guesses as to what folks would _commonly_ do, and just added the JS API to cover the rest. :)

Comment 3 by Nate posted on 12/22/2008 at 9:15 PM

The "hacks" into the libraries are great for doing things like a custom renderer for the cfgrid, removing pagination (along with allowing us to remove row selection) to me seems like a basic function that should be a part of the cfgrid implementation.

On the topic of the ExtJS libraries, is the whole lib included by Adobe or are only certain aspects of it (like the grid libraries implemented)?

Comment 4 by Akira posted on 12/22/2008 at 10:44 PM

Nate, as far as I know everything that is in Ext 1.1 is included in the CFIDE folder.

Ray, since Ext has changed their licensing model and moved to 2, do you know if Adobe is going to be including Ext 2 in a future update?

Comment 5 by Raymond Camden posted on 12/22/2008 at 11:52 PM

@Akira: I'm not aware of any public statement. Personally, I think that - in GENERAL - you should use what is provided and documented only. Yes, the full Ext library may be there, but I'd stick to the official stuff. If you want to do more, then I'd grab my _own_ copy of Ext (it's what, 5k??) and use that version. Make sense?

Comment 6 by Akira posted on 12/23/2008 at 12:03 AM

Ray, makes sense but I don't like the GPL 3 that is on the new version of the Ext library. The old one isn't easy to find on their website.

Comment 7 by Raymond Camden posted on 12/23/2008 at 12:05 AM

Ah, well, I was speaking in general. Personally I'm not a big fan of Ext. It seems a bit hard to use. Of course, I said the same about jQuery, and now I'm getting more used to it.

Comment 8 by Anthony Patch posted on 1/15/2009 at 4:03 PM

How do you output the result set in getentries.cfm in order to populate the grid via the bind attribute? In otherwords, what is in the getentries.cfm file? Do you have to use queryConvertForGrid? If so how? Much appreciated,
Tony

Comment 9 by Raymond Camden posted on 1/16/2009 at 1:04 AM

Yep, queryConvertForGrid.

Comment 10 by Anthony Patch posted on 1/16/2009 at 3:18 PM

Thanks. After reading LiveDocs, I found that you have to use queryConvertForGrid with serializeJSON in order to output correctly. ex:
<cfoutput>#serializeJSON(QueryConvertForGrid(query, page, pagesize))#</cfoutput>

It works like a charm.

Comment 11 by Nando posted on 2/1/2009 at 1:15 AM

I stumbled upon another way to remove pagination, which is to create your own footer under the grid. If you do that, it replaces the pagination footer with yours.

Here is how I've implemented it, adding a button to add a record with only a large red "+" icon in the middle of the button, and a delete button with an icon and the words "Delete Selected".

function initGrid() {
grid = ColdFusion.Grid.getGridObject("RecipeHerbGrid");
var gridFoot = grid.getView().getFooterPanel(true);
var bbar = new Ext.Toolbar(gridFoot);
bbar.addButton({
cls:"x-btn-text-icon",
icon:"icons/add.png",
handler:onAdd
});
bbar.addSeparator();
bbar.addButton({
text:"Delete Selected",
cls:"x-btn-text-icon",
icon:"icons/delete.png",
handler:onDelete
});
}

Heck, while i'm posting this, I should also just go ahead and post the handler functions, in case it helps anyone. Took me a long time to pull all this together:

function onAdd(button,event){
ColdFusion.Window.show('addRecipeHerbWindow');
// console.log(button);
// console.log(event);
}

function addRecipeHerb() {
//send data to CFC to add RecipeHerb, the result will be handled by handleResult function above
var f = document.frmRecipeHerb;
dataproxy.addNewRecipeHerb (
f.recipeVariationId.value,
f.herbId.value,
f.weight.value
);
ColdFusion.Window.hide('addRecipeHerbWindow');
ColdFusion.Grid.refresh('RecipeHerbGrid', true);
}

function onDelete(){
ColdFusion.Window.show('deleteRecipeHerbWin');
}

function deleteRecipeHerb(confirmMessage) {
// if user choose to delete, then send the CFC call, otherwise just sit back!
if (confirmMessage == 'yes')
{
var grid = ColdFusion.Grid.getGridObject("RecipeHerbGrid");
var record = grid.getSelections();
// remember, CF makes column names to all UPPERCASE, so dont forget to do that
dataproxy.deleteRecipeHerb(record[0].data.RECIPEHERBID);
}
ColdFusion.Window.hide('deleteRecipeHerbWin');
ColdFusion.Grid.refresh('RecipeHerbGrid', true);
}

function editRecipeHerb() {
var grid = ColdFusion.Grid.getGridObject("RecipeHerbGrid");
var record = grid.getSelections();
dataproxy.editRecipeHerb (
record[0].data.RECIPEHERBID,
record[0].data.THEWEIGHT,
record[0].data.PINYIN
);
ColdFusion.Grid.refresh('RecipeHerbGrid', true);
}

It's all wired to the back end using the cfajaxproxy tag.

Comment 12 by Michael Sinaysky posted on 6/27/2009 at 5:03 AM

Raymond,

Can you publish code for the getentries.cfm?

Comment 13 by Raymond Camden posted on 6/27/2009 at 6:48 AM

This should be it. It uses a BlogCFC database.

<cfquery name="entries" datasource="blogdev">
select *
from tblblogentries
<cfif len(url.sort) and len(url.dir)>
order by #url.sort# #url.dir#
</cfif>
</cfquery>

<cfset data = queryConvertForGrid(entries, url.page, url.pagesize)>
<cfset encoded = serializeJSON(data)>
<cfcontent type="text/json" reset="true"><cfoutput>#encoded#</cfoutput>

Comment 14 by Michael Sinaysky posted on 6/27/2009 at 11:58 PM

Raymond,

I am receiving fallowing error:
window:global: 'e' is undefined (http://localhost/CFGrid_Test/test.cfm?cfdebug=true, line 525)

This is a code for Test.cfm
<html>
<head>
<script>
function testit()
{
var myGrid = ColdFusion.Grid.getGridObject('entries');
myGrid.view.getFooterPanel().setVisible(false);
myGrid.view.refresh();
}
</script>
</head>

<body>
<cfform name="test">
<cfgrid autowidth="true"
name="entries"
format="html"
width="600"
bind="url:getentries.cfm?page={cfgridpage}&pagesize={cfgridpagesize}&sort={cfgridsortcolumn}&dir={cfgridsortdirection}">
<cfgridcolumn name="id" header="ID">
<cfgridcolumn name="price" header="Price">
<cfgridcolumn name="product" header="Product">
</cfgrid>
</cfform>
<cfset ajaxOnLoad("testit")>
</body>
</html>

This is a code for getentries.cfm

<cfset data = queryNew("id,price,product")>
<cfloop from=1 to=10 index="x">
<cfset total = randRange(20,100) & "." & randRange(1,99)>
<cfset product = "Product #X#">
<cfset queryAddRow(data)>
<cfset querySetCell(data, "ID", x)>
<cfset querySetCell(data, "price", total+0, x)>
<cfset querySetCell(data, "product", product, x)>
</cfloop>

<cfset data = queryConvertForGrid(getArtists, url.page, url.pagesize)>
<cfset encoded = serializeJSON(data)>
<cfcontent type="text/json" reset="true"><cfoutput>#encoded#</cfoutput>

Comment 15 by Raymond Camden posted on 6/28/2009 at 12:00 AM

Not sure what to tell you. Do you still get an error if you comment out everything in testit?

Comment 16 by Michael Sinaysky posted on 6/28/2009 at 4:44 AM

Never mind I figure out what is going on.

Gecko (and similar) browsers pass a reference to an event object as the first parameter when calling a function assigned to an intrinsic event handler this way. IE doesn't, it uses a global 'event' variable.
Local variable "event" here masks IE's global event variable. As soon as I Modified function as fallowing

function testit()
{
var e = e || window.event;
var myGrid = ColdFusion.Grid.getGridObject('entries');
myGrid.view.getFooterPanel().setVisible(false);
myGrid.view.refresh();
}
everything starts working.

I do have another question s about CFGRID

How I can change background color of the one sell (let say cell in column 3) depending of cell value in column 2

Thanks in advance.

Comment 17 by Michael Sinaysky posted on 6/28/2009 at 10:07 PM

Raymond,

One more question. Is it possible to populate CFGRID through cfajaxproxy call?

Comment 18 by Raymond Camden posted on 6/29/2009 at 6:49 AM

Yea - you just have to ensure your JavaScript seeds the data right. I believe I did a blog entry on this before, but I can't remember the URL offhand.

Comment 19 by Michael Sinaysky posted on 6/29/2009 at 4:20 PM

Raymond,

If you be able to find blog URL I will be very much appreciated.

Did you sow my question about changing background color on the grid cell depending of value in another grid cell?

Comment 20 by Raymond Camden posted on 7/1/2009 at 6:42 AM

Not having any luck - may want to resort to Google.

Comment 21 by Bill posted on 7/13/2009 at 11:00 PM

Ray,

Thanks for the tip, it works great. The problem with hiding the paging toolbar is that it leaves the user without a way to scroll through the records in the grid when they exceed what's visible. Is there a way to make the vertical scrollbar visible while the paging footer is hidden?

Comment 22 by Raymond Camden posted on 7/13/2009 at 11:04 PM

Um... I guess you would need to ensure you return all the rows. Do you?

Comment 23 by Bill posted on 7/15/2009 at 1:06 AM

Sort of. The grid is dynamically populated record by record, so at any given time there may be less records than would cause scrolling/paging.

Comment 24 by Ben Schwartz posted on 1/28/2010 at 8:49 PM

Hi,

I was using the method you suggest to remove the footer of a cfgrid as such:
var myGridA = ColdFusion.Grid.getGridObject('gridname');
myGridA.view.getFooterPanel().setVisible(false);
It was working really well until i upgraded to CF9 - and i guess they upgraded the ext library as well - now i get the following error:
myGridA.view.getFooterPanel is not a function

Do you have any idea what i can replace this with - it's kinda weird that upgrading wasn't backwards compatible.

Thank you very much in advance for your help.

Comment 25 by Raymond Camden posted on 1/28/2010 at 9:38 PM

No idea - but where I'd start is the Ext docs. That's where I found the original info for the older version.

Comment 26 by Debbie G. posted on 3/16/2010 at 2:16 AM

Did you find a way to set the background color of a grid cell? I don't want to hardcode the color because it differs from cell to cell. The "color" is actually the value of the column. I also want to set the text/font color to white if the background color is Red; otherwise, set text/font color to black.

I've tried the following without success:
<cfgridcolumn name="StatusColor" header="Status" bgcolor="StatusColor">

<cfgridcolumn name="StatusColor" header="Status" bgcolor="CX">

<cfgridcolumn name="StatusColor" header="Status" bgcolor="(CX EQ Green?green:yellow)">

Appreciate your help. In my search, I've found that several people have asked this question and no response has been given. I'm using ColdFusion 8, with an HTML format for CFGrid using the bind (instead of query) to populate the data.