I want to render a php view file in the cell of a CGridView.
Therefore I wrote this code:
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$dataProvider,
'columns'=>array(
array(
'value'=>array($this, 'renderPartial("_lineProblems")')
))));
But I get this error:
BookController and its behaviors do not have a method or closure named "renderPartial('_lineProblems' )".
The stack trace shows this as the problem:
call_user_func_array(array(BookController, "renderPartial('_lineProblems' )"), array("data" => line, "row" => 0, 0 => CDataColumn))
I don't understand the error. $this is an instance of BookController and BookController is a child of CController.
Found a solution with the help of another Yii programmer
$controller = $this;
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$dataProvider,
'columns'=>array(
array(
'name'=>'errors',
'value'=>function($data, $row) use ($controller){
return $controller->renderPartial('_lineProblems', array('errors'=>$data->errors), true);
}
)
),
));
Related
i have a admin page with CGrideView , but when i want to change my button column to add some other buttons gives this error : CButtonColumn and its behaviors do not have a method or closure named "getId".
admin action :
public function actionAdmin()
{
$model=new Block('search');
$model->unsetAttributes(); // clear any default values
if (isset($_GET['Block'])) {
$model->attributes=$_GET['Block'];
}
$this->render('admin',array(
'model'=>$model,
));
}
admin view :
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'block-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
'name',
'content',
'type',
'enable',
array(
'class'=>'CButtonColumn',
'template' => '{view}{update}',
'buttons' => array(
'update' => array(
'url' => 'Yii::app()->controller->createUrl("update", array("name"=>$data->name))'
),
'view' => array(
'url'=>'CController::createUrl("view", array("name"=>$data->name))'
),
),
),
)));
solved! the reason is in the :
'view'=>array(
'url'=>'CController::createUrl("view",array("name"=>$data->name))'
),
it should be :
'view'=>array(
'url'=>'Yii::app()->controller->createUrl("view", array("name"=>$data->name))'
),
and why ?
because ():
Because Yii::app()->controller it is instance Controller of current application. Controller have property private $_id. CController::createUrl it is just static method. In method createUrl() calls method $this->getId(), but when you call static method instance is not created-#DanilaGanchar .
so in CController::createUrl it can't find the id of controller and for use that i should give it argument like this CController::createUrl("/page/view",array("name"=>$data->name)) i try that now and worked
The order of elements in template must be equal to the order of element in buttons. You have {view}{update} as the template, but you have defined update button first! So I think changing 'template'=>'{view}{update}' into 'template'=>'{update}{view}' probably can solve your problem.
I have a search form, which returns a bunch of images. Because their number can be high, I would prefer having the results displayed using pagination. However, I cannot seem to get it to work properly. I have moved everything to the view to keep things as simple as possible.
Here is my code snippet for the search and pagination:
$searchData = $model->search(); // this is the result of the search
$pages = new CPagination($searchData->itemCount);
$searchData->setPagination($pages);
$pages->applyLimit($searchData->criteria);
$pages->pageSize = 2;
Then, I display the results using a "foreach" statement:
foreach($searchData->getData() as $data)
{
// results displayed here
}
Finally, I have the CLinkPager widget:
$this->widget('CLinkPager', array(
'pages' => $pages,
'header' => 'Отиди на страница: ',
'nextPageLabel' => 'Следваща',
'prevPageLabel' => 'Предишна',
)); `
The problem is: there is not a relation between the widget and the displayed results.
For instance, if I get 4 results, the widget correctly shows that there are 2 pages. However, the results are not displayed in two pages, all are shown in one and clicking the CLinkPager links does nothing.
I have done pagination in the past successfully before, but for all the data using
model()->findAll().
How do I state the relation between the pagination widget and the search results... ?
Thank you for your time.
I think you are possibly overcomplicating the process. You could more easily use CListView widget to display your results with pagination.
Your controller may have this;
public function actionIndex(){
$model = new Model;
$this->render('index', array('model' => $model);
}
Your model needs to have a search method that returns an instance of CActiveDataProvider, for example
public function search() {
$criteria = new CDbCriteria;
$criteria->compare('id', $this->id, true);
$criteria->compare('title', $this->title, true);
$criteria->order = 'sortOrder';
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
));
}
Then in your view file you can use this code;
$this->widget('widgets.CListView', array(
'dataProvider' => $model->search(),
'itemView' => '_list',
'template' => '{pager}{items}',
'pager' => array(
'nextPageLabel' => 'Следваща',
'prevPageLabel' => 'Предишна',
)
));
You can extend the CListView by putting this in your extensions folder, and change the page size there.
<?php
Yii::import('zii.widgets.CListView');
class CustomListView extends CListView {
public function init() {
if ($this->dataProvider !== null)
$this->dataProvider->pagination->pageSize = 30;
$this->dataProvider->pagination->nextPageLabel => 'Следваща';
$this->dataProvider->pagination->prevPageLabel => 'Предишна';
parent::init();
}
}
Then, use the CustomListView as follows:
<?php $this->widget('CustomListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'_view',
)); ?>
You do not need to use CLinkPager widget directly this way.
I have two table Event and EventCategory. I am using zii.widgets.grid.CGridView widget to display all the events in the admin section.
I have created the following relations between tables.
Relation in EventCategory model:
'event' => array(self::HAS_MANY, 'Event', 'category_id'),
Relation in Event model:
'category' => array(self::BELONGS_TO, 'EventCategory', 'category_id'),
The following code I am using to display the Events:
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'event-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'summaryText'=> '',
'columns'=>array(
array('header'=>'Id','name'=>'event_id','filter'=>''),
'event_code',
'category.evntcatm_name',
'event_name',
array(
'class'=>'CButtonColumn',
'htmlOptions'=>array('class'=>'actions aligncenter'),
'deleteButtonImageUrl'=>false,
'updateButtonImageUrl'=>false,
'viewButtonImageUrl'=>false
),
),
)); ?>
'category.evntcatm_name' doesn't display anything. It is just creating the blank column with NO ERROR. What I am missing here.
Please try something like it
$data->category->evntcatm_name
You should use code like this:
'columns' = array(
/*YOUR DATA*/
array(
'name' => 'category_id',
'value' => function($data) {
return !empty($data->category) ? $data->category->evntcatm_name : null;
}),
)
This way can solve your problem with "Trying to get property of non-object". If you see blank cell in grid that means you miss relation (or it doesnt exist, in this way you should check relation condition or database)
Here is a few wild guesses:
Is category.evntcatm_name correctly spelled?
Is there actually data in the evntcatm_name field to begin with?
I know it might sound too simple to miss, but the error almost has to be on that level.
Try finding a category using the primary key and output it's evntcatm_name.
$cat = EventCategory::model()->findByPk(1);
echo $cat->evntcatm_name;
Maybe if you could share your schema for those two tables?
You can use
array(
'header' => 'Category Title',
'value' => '$data->category->evntcatm_name'
),
instead of 'category.evntcatm_name'
The model instance is not object now in the Cgidview:
Try
$data['category']['evntcatm_name'];
In views controller name can be achieved by $this->id, but in CGridView $this->id evaluation results in another name (may be gridview widget name). (1) How can I get controller name in cgridview?
Also I tried to define a variable ($thisCtl = $this->id) before calling CGridview. Although $thisCtl has the controller name, in CGridview evaluation process it is not defined. (2) Is there any way to pass a parameter to CGridView?
<?php
$thisCtl = $this->id;
$data = $model->search();
$this->widget('bootstrap.widgets.TbExtendedGridView', array(
'id'=>'insurance-grid',
'dataProvider'=>$model->search(),
//'filter'=>$model,
'columns'=>array(
'id',
'registeration_date',
'modification_date',
array(
'htmlOptions' => array('nowrap'=>'nowrap'),
'class'=>'bootstrap.widgets.TbButtonColumn',
'viewButtonUrl'=>'Yii::app()->createUrl("$thisCtl/view", array("id"=>$data["id"]))',
'updateButtonUrl'=>'Yii::app()->createUrl("$this->id/update", array("id"=>$data["id"]))',
),
),
));
?>
Since it appears you wish to use the controller value within the column values, you can do the following to get the controller name:
$this->grid->controller->id
As you are within a TbButtonColumn, you can access the grid property (since TbButtonColumn extends from CButtonColumn which in turn extends from CGridColumn) to access the TbExtendsGridView (which ultimately extends from CGridView) where you in turn access the controller property of the grid (which is defined by the widget parent), and finally the get id of the controller.
Then, assuming all your other code is correct, you would specify your gridview like so:
<?php
$data = $model->search();
$this->widget('bootstrap.widgets.TbExtendedGridView', array(
'id'=>'insurance-grid',
'dataProvider'=>$model->search(),
//'filter'=>$model,
'columns'=>array(
'id',
'registeration_date',
'modification_date',
array(
'htmlOptions' => array('nowrap'=>'nowrap'),
'class'=>'bootstrap.widgets.TbButtonColumn',
'viewButtonUrl'=>'Yii::app()->createUrl($this->grid->controller->id."/view", array("id"=>$data["id"]))',
'updateButtonUrl'=>'Yii::app()->createUrl($this->grid->controller->id."/update", array("id"=>$data["id"]))',
),
),
));
I haven't used any of the Tb extensions myself, by so long as they did not alter the built in behavior of the objects they extended, the above should work as desired.
the problem is that $this in CGridView refers to it's widget. So we should use a global function to get current controller name:
Yii::app()->getController()->getId();
the code should look like:
<?php
$thisCtl = $this->id;
$data = $model->search();
$this->widget('bootstrap.widgets.TbExtendedGridView', array(
'id'=>'insurance-grid',
'dataProvider'=>$model->search(),
//'filter'=>$model,
'columns'=>array(
'id',
'registeration_date',
'modification_date',
array(
'htmlOptions' => array('nowrap'=>'nowrap'),
'class'=>'bootstrap.widgets.TbButtonColumn',
'viewButtonUrl'=>'Yii::app()->createUrl("'.Yii::app()->getController()->getId().'/view", array("id"=>$data["id"]))',
'updateButtonUrl'=>'Yii::app()->createUrl("'.Yii::app()->getController()->getId().'/update", array("id"=>$data["id"]))',
),
),
));
?>
Thanks to this post Getting Current Controller ID in Yii
Suppose I have model User which have many to many relation to itself named as friends.
so $user->friends (or $model->friends in view) gives me an array of User objects. I wanted to display the friends as gridview. But CGridView data as dataProvider object. Googling for it found the way to convert array of model objects to dataProvider object as given below.
$this->widget('zii.widgets.grid.CGridView', array(
'id' => 'gridUser',
'dataProvider' => new CArrayDataProvider($model->friends, array()),
));
Now using this I get an error
Property "User.id" is not defined.
UPDATE
public function relations()
{
return array(
'friends' => array(self::MANY_MANY, 'User', 'friendship(user_id, friend_id)'),
);
}
I use two stage building the provider shown below. But I found that it gives you trouble in terms of Pagination. I have not bothered to resolve that problem since am doing other things
$dataProvider = new CArrayDataProvider('User');
$dataProvider->setData($model->friends);
$this->widget('zii.widgets.grid.CGridView', array(
'id' => 'gridUser',
'dataProvider' =>$dataProvider,
));
That being said, your code should work (see the example below from API docs). I suspect there is wrong attribute in your relations than the provided code. Re-check the relation definition if it is ok
From Yii docs:
$rawData=Yii::app()->db->createCommand('SELECT * FROM tbl_user')->queryAll();
// or using: $rawData=User::model()->findAll(); <--this better represents your question
$dataProvider=new CArrayDataProvider($rawData, array(
'id'=>'user',
'sort'=>array(
'attributes'=>array(
'id', 'username', 'email',
),
),
'pagination'=>array(
'pageSize'=>10,
),
));
Got it :) , i can use CActiveDataProvider instead of CArrayDataProvider as given below
$this->widget('zii.widgets.grid.CGridView', array(
'id' => 'gridUser',
'dataProvider' => new CActiveDataProvider('User', array(
'data'=>$model->friends,
)),
//...... columns display list.....
));
Anyways thanks for the reply #Stefano