Insert a multirow header in CGridView

  1. Extending CGridView.
  2. Configuring the application.
  3. Using it.
  4. The code.

The CGridView widget is very useful and customizable, but sometimes you need a little more. One limit I found is to have only one row for headers; yes, you can write each column header in more than one row, but just inside the single cell. I was looking instead for the possibility to use more than one row, with different structure one from the others. This way you can write columns grouping headers, and obtain a nicer view.

Extending CGridView.

First I was scared about the idea of extending a widget (I'm a newbie in Yii), but it's easier than I thought.

Below there is the code. The core is the overriding of renderTableHeader() function, but first there is a new parameter to insert in the class properties: addingHeaders.

This parameter is an array in which each element represents a single header row and is, again, an array containing the single cells definition. Each cell has the text (key) to be viewed as header and the number (value) of columns to span across.

Clearly, the total width (summing up the values) of each header row, cannot be more than the real number of columns. Can be less... if you like it.

The "normal" header row, as defined in the usual column header attributes, is rendered after the added rows.

Configuring the application.

The file, as usual, is to be saved in the components folder, with CGridViewPlus as name. Finally you have to declare it in the configuration file main.php, adding this row in the components section:

'CGridViewPlus' => array('class' => 'components.CGridViewPlus',),

Using it.

The use of this feature is very easy. The widget has to be called this way:

$this->widget('CGridViewPlus', array(

... and in the list of properties you can add the new parameter as explained before:

'addingHeaders' => array(
         array('group A' => 2, 'group B' => 5),             // first row
         array('sub j' => 3, 'sub k' => 2, 'sub l' => 2),   // second row

The code.



class CGridViewPlus extends CGridView {

    public $addingHeaders = array();

    public function renderTableHeader() {
        if (!empty($this->addingHeaders))


    protected function multiRowHeader() {
        echo CHtml::openTag('thead') . "\n";
        foreach ($this->addingHeaders as $row) {
        echo CHtml::closeTag('thead') . "\n";

    protected function addHeaderRow($row) {
        // add a single header row
        echo CHtml::openTag('tr') . "\n";
        // inherits header options from first column
        $options = $this->columns[0]->headerHtmlOptions;
        foreach ($row as $header => $width) {
            $options['colspan'] = $width;
            echo CHtml::openTag('th', $options);
            echo $header;
            echo CHtml::closeTag('th');
        echo CHtml::closeTag('tr') . "\n";


Sorry for my bad english.