CGridView with dynamic columns

I haven’t been able to track down an answer to this question, but is there a way to populate a CGridView object using a CActiveDataProvider that can have varying columns? I am using a CGridView to display comparisons of different products, but it is a general template page that gets different products and different items to compare. For example:

I want to show comparisons of Product A with Products B, C, and D

or I want to show comparisons of Product B with Products C, D, and E

Thanks in advance.

Is it possible to send an array of columns as an input to the CGridView?

You may choose to base your solution on CArrayDataProvider.

/Tommy

Thanks for the reply Tommy.

I am still new to Yii, but if I did it that way, wouldn’t I have to load up the array with all of the data from the tables before calling the view instead of just being able to select which columns of data from the active records that I wanted to show in the view?

If you just want to select columns to show, yes, you can populate the an array and attach to the ‘columns’ key of CGridView, before instantiating it. Is that what you meant?

/Tommy

I tried that, but maybe I didn’t implement it properly. I keep getting the following error:

[font=Verdana][size=2]Property "CDataColumn.0" is not defined.[/size][/font]

Here is my controller code:





	public function actionProductA()

	{

		$columnsArray = array(

			array(            

				'name'=>'',

				'type'=>'raw',

				'value'=>'$data->spec',

			),

			array(    

				'header'=>Yii::t('app', 'Product A'),

				'type'=>'raw',

				'htmlOptions'=>array('style'=>'text-align: center'),

				'value'=>'$data->productA',

			),

			array(            

				'header'=>Yii::t('app', 'Product B'),

				'type'=>'raw',

				'htmlOptions'=>array('style'=>'text-align: center'),

				'value'=>'$data->productB',

			)

		);

		

		$comparisonDataProvider=new CActiveDataProvider('ModelSpecsProducts',array(

			'criteria'=>array(

				'condition'=>'comparison_spec=1',

				'order'=>'sortorder ASC',

			),

		));

		

		$dataProvider=new CActiveDataProvider('ModelSpecsProducts',array(

			'criteria'=>array(

				'condition'=>'comparison_spec=0',

				'order'=>'sortorder ASC',

			),

		));

		

		$this->render('productView',array(

			'product'=>Products::model()->FindByPk(3),

			'comparisonDataProvider'=>$comparisonDataProvider,

			'dataProvider'=>$dataProvider,

			'columnsArray'=>$columnsArray,

		));

	}



Here is my view code:




$this->widget('zii.widgets.grid.CGridView', array(

                    'id'=>'products-compared-grid',

                    'dataProvider'=>$comparisonDataProvider,

                    'enablePagination'=>false,

                    'summaryText'=>'',

                    'columns'=>array(

		            $columnsArray,

                    ),

                )); 



First change like this




 'columns'=>$columnsArray,



/Tommy

I think I found my error, I should have removed the array( from before the $columnsArray variable in the view.

LOL you found that as I was typing it. Thanks for all your help.

Yes, this is possible. Examine the code sample below.




    public function actionArray() {

        

        $columns = array(

            'optid',

            'symbol',

            array('name' => 'g_date', 'value' => 'date("m/d/y", strtotime($data->g_date))'),

            'g_price',

            array('name' => 'expire_date', 'value' => 'date("m/d/y", strtotime($data->expire_date))',),

            'g_qty',

            array(

                'name' => 'target_price',

                'value' => '$data->target_price',

                'footer' => '<b>TOTAL:</b>'));


        $dataProvider = new CActiveDataProvider('MyModel', array(

                    'criteria' => array(

                        'with' => 'myRelated',

                        'together' => true,

                        'condition' => 'user_id=' . Yii::app()->user->id,

                    ),

                    'pagination' => false,

                        //array(pageSize'=>100),

                ));


        $this->render('array', array(

            'dataProvider' => $dataProvider,

            'columns' => $columns));

    }



Edit: Sorry, I got distracted and finished posting this much later than I started it.

Thanks for helping. Its good to know I can mix arrays with ordinary fields in the column list.

Is dynamic column can be implemented if the cgridview update through ajax?

Solved. In the controller,instead of rendering the view then calling a new dataprovider for the gridview.

just call the gridview with different column or different dataprovider.