Grid Documentation

Wednesday, October 20th, 2010|Beginner tips|by Romans

Grid is a powerful UI element used in almost any web application. Some frameworks decide not to implement them at all. Others rely on full-featured JavaScript implementation and only provide data source as requested. Agile Toolkit builds grids in HTML, then enhances them through JavaScript. JavaScript widget then communicates with back-end to perform additional features for the grid. This post will look more in-depth on what can you do with grids.

Power of Agile Toolkit Grids

Before we continue, let’s do the basics. Grab a up-to-date Agile Toolkit version from trunk (or 3.9.1+ if it is released). As any other object you can add grid anywhere. We are going to use default JUI templates, but you are free to specify your own template.

Basics – getting started



This should get you started. You can call addColumn as many times as you need. First argument is always a type. Second is a system name. Third is label. You may omit label, in which case it will be constructed from system name.

When you are using grid on your page, you may abbreviate variable as $g. Do not use $g for any other purposes.

Specifying data source

If you already have array of hashes you can specify it as a source for grid using $g->setStaticSource(). This method also works with array of objects, which is handy when you are fetching data through SOAP or parsing XML file.

Grids support dynamic queries. You start using them if you call $g->setSource($table). This will create a new object $g->dq which you can access directly and add additional conditions or perform joins. You can also call $g->dq->debug() if you want to see, what type of query is being used. Set source will automatically select all fields from $table. You can also specify list of fields yourself as 2nd argument to the function call.

Grids assume that you will have “id” field for your data and it is used in some operations.

Finally if you are using Models you can associate grid with a model through controller by using $g->setController(‘Controller_User’); In this case Controller will add all actual fields into your grid automatically.

If none of those options fail, you can redefine function fetchRow() This function needs to set $this->current_row to the next associative array (hash) from data set every time it’s called or return false.

Lister, CompleteLister and Grid

Implementation of Grid relies on CompleteLister, which in turn relies on Lister. Data fetching is implemented inside Lister and is inherited all the way to Grid. If you do not like the way how data is presented, you should choose one of those 3 classes according to those criterias:

  • Does data needs to be presented in columns, one line per data entry? If yes – use Grid
  • You wish to use your own template, and simply repeat it for every data entry? If yes – use Lister
  • Your template have part which repeats, but then there is a some markup before and after repeating part (such as <ul>)? If yes – use CompleteLister

If you are tracing functions, always look at the inheritance between those 3 functions.

Grid column formatting

Benefit of using columns allows you to format them using either standard formatters or define your own formatting rules. For instance if column in the database contains money, you can display it accordingly with $g->addColumn(‘money’,'amount’);

Formatters most always will only adjust the format and therefore you can use several formatters together.


Basic column formats are:

  • text – simply displays text
  • shorttext – similar to text, but if it’s longer than 60 characters it will be cut in the middle to keep output compact (it sets title to full text)
  • html – allows you to output HTML [todo]
  • money – will perform number formatting (2 digits for coins) and will highlight negative money in red.
  • date – will format date according to config locale/date. Default is d/m/Y. Field format must be Y-m-d.
  • datetime – will format date according to config locale/datetime. Default is d/m/Y H:i:s
  • nowrap and wrap – deals with automatic wrapping into newlines
  • template – allows you to use SMlite for formatting column. Call $g->addColumn(‘template’,'full_name’)->setTemplate(‘<?$name?> <?$surname?>’);
  • nl2br – will substitute newlines with br’s: [todo] must be default for text
  • link – will add a link to a subpage identical to column short name. $g->addColumn(‘link’,'edit’); would link to thispage/edit.html?id=123

Grid also supports few more advanced formatters:

  • expander – similar to link, but will open that page inside expander
  • inline – will make cells editable. Clicking in a cell will insert a mini-form with one field. Once you leave the field, data will be saved and row reloaded.
  • button – adds standard button to grid with standard markup. If you need to change mark-up – make your own type. If button is clicked frontend will perform AJAX request with button_short_name=$id (but will also add button_full_name=$id). Creative use of buttons can lead to interesting results, such as:
  • prompt – similar to button, but will ask user to confirm.
  • delete – same as prompt, but will attempt to delete current column. This only works if data source supports deleting records. You can re-define action taken after click in $g->_performDelete($id) function. By default it is going to re-use $g->dq (which also applies all limitations you have on your grid)
  • prompt – will use standard javascript call to ask user “Enter value” then will pass it in $_GET['value']. Sends request through ajaxec().
  • checkbox – adds checkbox to be used by addSelectable()

Adding your own

You can add your own formatters by adding functions starting with format_. For instance you may use different colors for your status messages. Define: format_status($field) and use format_money as example on how to set column colors.

Formatting of complete row

Column formatting is done by formatRow(), and you might also re-define that function. After formatting is done, value of $g->current_row will be set to row template. Grid pre-constructs template with defined columns, while both Listers will simply rely on template they are given.

Adding other objects inside Grid

Grid as any other view in Agile Toolkit can be used to add additional objects into. A most common use is to add buttons on top of the grid. Grid even have a shortcut you can use $g->addButton(‘Hello’); (more info

$g->add(‘HelloWorld’,null,’grid_buttons’); // adds words Hello world where buttons are supposed to be. You can add a form there, with minimalistic template, which will help you to add either dropdown or hidden field for selectable fields (more below)


Grid’s paginator is implemented in a separate class. $g->addPaginator(25); is a shortcut to add it. You can also use paginator with listers, but you will need to add it manually. Argument 25 defines how many records per page you want to see.

Paginator implementation have it’s own class which you can change or assign new template.


$g->addQuickSearch(array(‘name’,'surname’)); will add a form for quick searches and will automatically look for that phrase inside the columns you specify

Both Paginator and QuickSearch are using $grid->dq.


Call this and pass it Form_Field object. It will add checkboxes to the grid. Selected checkbox value will appear in the field in JSON format. (See


This will add a new row at the bottom of the grid with Totals:

Sorting grids

You can make any column sortable by calling $g->addColumn()->makeSortable() after you added that column. In some cases what you use in “order” in SQL is different from the column name, so you can pass it as the argument to makeSortable(). This will make column header clickable and will show arrow with selected sort order.

Redefining template for your Grid

Pick default grid.html and customize. It is quite straightforward, you will need to define row and column as well how to display totals.

JavaScript bindings

Ability to use JavaScript adds a whole new dimension to grid usability. Starting from 3.9.1 grids are automatically enhanced with ui.atk4_grid. This allows you to use the following:


And other functions. Here is a list:

  • reloadRow(id)
  • removeRow(id)
  • highlightRow(id)

There are more functions but they are currently undocumented and may be discontinued or not work.

Finally you can use $g->js()->reload(), to re-load grid content without affecting other elements on the page.

Use with Models

Here is a sample code:


Feedback please!

Please write me a comment. I love them.


Posted October 23, 201010:25 am

Nice one. Wish, you would have posted that a few days earlier :)

Just in case you work with static source List/Grid, then, to implement pagination feature you can do it this way:

$paginator = $this->add("Paginator");
// set items per page
// finally, make paginator use and tune your static source (before passing to grid)

Also, from own experience, you will be willing to use:
$grid->safe_html_output = false; // to allow html code injection
$grid->addColumn("html",…); // that would be alternative for one column only.


Posted October 24, 20101:36 am

safe_html_output also works on listers. If you are permitting HTML you may become vulnerable to JS injection.

Posted October 25, 20105:34 pm

note addSelectable() and makeClickable() will conflict. to be more precise, after checkbox is clicked, event is passed further to makeClickable and action is performed.

Posted October 25, 201011:21 pm

It’s not as the are conflicting, but they do what they supposed to. When you click on the checkbox, it becomes selected but you are sent to a new page. It’s just same as if you do <a href=”otherpage.html” onclick=”javascript: alert(123)”> – you will see alert then will be sent to other page.

However, jancha, do you think framework should perform any checks to make sure you are not using those two together?

Posted October 26, 20107:23 am

At minimum, it should be made possible to easily configure the behaviour. Also this is more general example. Event pass by or preventing as well as prioritizing would be very cool to have.


Or something similar. JQuery already has support for this.

Posted October 26, 20107:56 am

if jQuery supports it, then you can call it from js().

Thanks, i’ll take a look.

Posted December 26, 20129:16 am

Demo site is offline. Is there another location available for inspiration? Thank you!

Posted December 26, 201210:23 pm

Demo links don’t work. I guess this is the new location: