CGridview custom field sortable - yii

I had created with custom field in yii Cgridview but how to make that sortable. The custom field value is from a function in the model. I want to make this field sortable?
Can someone help me?

In the search function of your model, where customField is the name of your field:
// ...other criteria...
$criteria->compare('customField',$this->customField);
$sort = new CSort();
$sort->attributes = array(
'customField'=>array(
'asc'=>'customField ASC',
'desc'=>'customField DESC',
),
'*', // this adds all of the other columns as sortable
);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
'sort'=>$sort,
));
You may also need to update rules and attributeLabels in your model to reflect the new custom field.

There is a detailed description about searching on custom fields at this URL:
Using standard filters in CGridView custom fields

Related

Add column from another table to CGridView

Hi I'm using yii crud and trying to add a column from another table to Admin view
This is my admin view CGridView widget code.
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'package-days-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
'package_days_id',
'package_days_description',
array(
'header' => 'Package Title',
'name' => 'package_days_package_id',
'value' => function ($data){
echo $data->packagePackagedays->package_title;
}
),
array(
'class'=>'CButtonColumn',
),
),
)); ?>
And this is relations function in 'PackageDays' model.
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'packagePackagedays' => array(self::BELONGS_TO, 'Packages', 'package_days_package_id'),
);
}
This is search function in 'PackageDays' model.
public function search()
{
// #todo Please modify the following code to remove attributes that should not be searched.
$criteria=new CDbCriteria;
$criteria->with = "packagePackagedays";
$criteria->compare('package_days_id',$this->package_days_id);
$criteria->compare('packagePackagedays.package_title',$this->package_days_package_id);
$criteria->compare('package_days_description',$this->package_days_description,true);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
I added the column successfully but I can't search values of newly
added column.
It would be great if someone can looking to it
Make sure you added package_days_package_id as a public property of your Packages model. Otherwise $this->package_days_package_id doesn't exist
class Packages extends CActiveRecord{
public $package_days_package_id;
...
Also Make sure you added package_days_package_id in your "safe" validation rule for the "search" scenario (also in your Packages model). Without this, the value you type in the text box won't be assigned to your $this->package_days_package_id
public function rules(){
return array(
...
// The following rule is used by search()
array('bunch, of, stuff, ..., package_days_package_id', 'safe', 'on'=>'search'),
If you also want the grid column to be sortable on click, you'll also have to create a custom CSort and provide it to your CActiveDataProvider

Dynamically create CGridViews that show different data

I'm new to Yii, and I'm having a hard time figuring this out. I want to show multiple CGridViews on a page depending on the options that a user chooses, with each gridview only showing the records for that option. In this case, the options are job statuses, like open, closed, in progress, etc.
I've got some code working to show multiple grid views by looping through an array, but I'm not sure how to filter them:
$test = array(1,2,3,4,5);
foreach ($test as $value) {
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'job-grid',
'dataProvider'=>$model->search(),
'columns'=>array(
'ID',
'CustomerCompany',
'FirstName',
'LastName',
/* etc */
),
));
}
Any ideas about how I can go about filtering each gridview from the values in the array?
Thanks!
UPDATE
Ok, I figured out how to do what I was trying to do. I'm handling it in the controller like this:
public function actionBoard()
{
$models = array();
$statuses = JobStatus::model()->findAll();
foreach ($statuses as $status)
{
$model=new Job('search');
$model->unsetAttributes(); // clear any default values
if(isset($_GET['Job']))
$model->attributes=$_GET['Job'];
$model->Status = $status->ID;
$models[$status->Status] = $model;
}
$this->render('board',array('models'=>$models));
}
So I find all the statuses, then use the ID field to do a search, put the result in an array, then pass it to the view. I handle it like this in the view:
foreach ($models as $status)
{
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'job-grid',
'dataProvider'=>$status->search(),
'columns'=>array(
'ID',
'CustomerCompany',
'FirstName',
'LastName',
'Phone1',
'Phone2',
/* etc */
),
));
Basically, creating a gridview for each "status" in the array of "statuses". Seems to work, just took some time to think of it in MVC terms instead of the old ASP.NET databinding method that I'm used to.
You asked for different CGridViews, so here it is:
Go in your model.
Now, you need to write some new search() methods.
Within each method, you will specify the values that you want, like these 2 methods:
public function searchA() {
// Warning: Please modify the following code to remove attributes that
// should not be searched.
$criteria = new CDbCriteria;
$criteria->compare('id', $this->id);
$criteria->compare('email', $this->email, true);
$criteria->compare('password', $this->password);
$criteria->compare('created', $this->created);
$criteria->compare('lastmodified', $this->lastmodified);
$criteria->compare('confirmed', $this->confirmed);
$criteria->compare('is_human', 1);// this is a human
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
));
}
public function searchB() {
$criteria = new CDbCriteria;
$criteria->compare('id', $this->id);
$criteria->compare('email', $this->email, true);
$criteria->compare('password', $this->password);
$criteria->compare('created', $this->created);
$criteria->compare('lastmodified', $this->lastmodified);
$criteria->compare('confirmed', $this->confirmed);
$criteria->compare('is_human', 0);//this is not a human, maybe a donkey ... who knows
$criteria->compare('username', $this->username, true);
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
));
}
now that you have your search methods, use the needed search method for each cgridview
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'job-grid',
'dataProvider'=>$model->searchA(),
'columns'=>array(
'ID',
'CustomerCompany',
'FirstName',
'LastName',
/* etc */
),
));
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'job-grid2',
'dataProvider'=>$model->searchB(),
'columns'=>array(
'ID',
'CustomerCompany',
'FirstName',
'LastName',
/* etc */
),
));
simple
ps: as a trick, you may want to use constants, like:
const CONSTA = 1;
const CONSTB = 2;
and use then in the model as:
self::CONSTA
or outside the model as:
ModelName::CONSTA
by using const, if your values change in time, you dont have to modify the entire code and you dont have to look all over the project for those values
You should begin at the data part of the problem: First try to create several data providers that return the results that you want. If you used Gii to auto-generate some models, you can look into the search() method there to see an example how you can create such a provider with different query conditions. You should try to keep this code in a model somewhere. For example you could create a searchByStatus($status) method, which returns a data provider for the given status.
Then in the controller you can fetch several data providers from this method, one for each status you want, send them to the view and finally feed them into different CGridViews.
Here is a wiki for dynamic gridviews in the same view.

Assign model to CActiveForm permanently

It is possible to assign model to be able to render any inputs without $model attribute on each field create?
Something like:
$form = $this->beginWidget( 'CActiveForm', array( 'model' => new Model , ... ) );
$form->textField('onlyAttributeHere');
??
Thanks
As of yii 1.1.10 it's not possible.
You can however extend the CActiveForm class, and add a new variable for this, but you will also have to change all the other methods(mainly html helpers) in that class, to use the new variable as the model.

Yii cgridview give reference to checkbox

Because when adding the CCheckBoxColumn to my vgridview in a form, in return I have no precise index for working with the checked box data's. So I try to add the 'uncheckValue' but I am unable to link it to the reference value of my table. Is there a way to access this value for the current row ? (the $data->reference in my code return a Undefined variable).
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'gview',
'dataProvider'=>$dataProvider,
'columns'=>array(
'client',
'reference',
array(
'class'=>'CCheckBoxColumn',
'id'=>'CB',
'selectableRows'=>2,
'checkBoxHtmlOptions'=>array(
'uncheckValue'=>$data->reference, ),
)),));
Tks anyone could put me on the way (if there is one... )
I finally find one way is to extend CCheckBoxColumn.
As inside this code I have access to $data. Now my form return checkbox with his 'name' as the 'reference' column of my table, so I can do further batch treatment.
The uncheckValue hidden field was not suitable as it was only giving index for unchecked fields (!).
I believe this code should not stay in view but in extension...
Any comments still welcome....
Yii::import('zii.widgets.grid.CCheckBoxColumn');
class LIndexCheckBoxColumn extends CCheckBoxColumn {
public $linkId;
public function renderDataCellContent($row,$data)
{
if($this->value!==null)
$value=$this->evaluateExpression($this->value,array('data'=>$data,'row'=>$row));
else if($this->name!==null)
$value=CHtml::value($data,$this->name);
else
$value=$this->grid->dataProvider->keys[$row];
$checked = false;
if($this->checked!==null)
$checked=$this->evaluateExpression($this->checked,array('data'=>$data,'row'=>$row));
$options=$this->checkBoxHtmlOptions;
//$name=$options['name'];
$varLink=$this->linkId;
$name=$data->$varLink;
unset($options['name']);
$options['value']=$value;
$options['id']=$this->id.'_'.$row;
echo CHtml::checkBox($name,$checked,$options);
}
}
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$dataProvider,
'columns'=>array(
'client',
'reference',
array(
'class'=>'LIndexCheckBoxColumn',
'id'=>'cb',
'selectableRows'=>2,
'linkId'=>'reference',
)),));

Yii CListView: url get-params redefining

Using the sorting and pagination in ClistView we have urls like:
controller/action?Model_page=NUM&Model_sort=COL.
Is it possible to make urls look like
controller/action?page=NUM&sort=COL.
and if it is possible, how can i make it?
Yes, you can set these parameters when you create your CActiveDataProvider:
$myDataProvider = new CActiveDataProvider('MyModel', array(
'sort'=>array(
'defaultOrder'=>'id DESC',
'sortVar'=>'sort' // set the sort parameter
),
'pagination'=>array(
'pageSize'=>5,
'pageVar'=>'page' // and and page param here
),
));