Dynamically create CGridViews that show different data - yii

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.

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

Creating Prestashop back-office module with settings page

I'm creating a back-office module for Prestashop and have figured out everything except the best way to display the admin page. Currently I'm using the renderView() method to display the content of view.tpl.
I would like to display a table with values and an option to add a new row. Should I just create it in the view.tpl or is there a better way? I've seen the renderForm() method but haven't figured out how it works yet.
The biggest question I have is, how do I submit content back to my controller into a specific method?
ModuleAdminController is meant for managing some kind of records, which are ObjectModels. Defauly page for this controller is a list, then you can edit each record individually or view it's full data (view).
If you want to have a settings page, the best way is to create a getContent() function for your module. Besides that HelperOptions is better than HelperForm for this module configuration page because it automatically laods values. Define the form in this function and above it add one if (Tools::isSubmit('submit'.$this->name)) - Submit button name, then save your values into configuration table. Configuration::set(...).
Of course it is possible to create some sort of settings page in AdminController, but its not meant for that. If you really want to: got to HookCore.php and find exec method. Then add error_log($hook_name) and you will all hooks that are executed when you open/save/close a page/form. Maybe you'll find your hook this way. Bettter way would be to inspect the parent class AdminControllerCore or even ControllerCore. They often have specific function ready to be overriden, where you should save your stuff. They are already a part of execution process, but empty.
Edit: You should take a look at other AdminController classes, they are wuite simple; You only need to define some properties in order for it to work:
public function __construct()
{
// Define associated model
$this->table = 'eqa_category';
$this->className = 'EQACategory';
// Add some record actions
$this->addRowAction('edit');
$this->addRowAction('delete');
// define list columns
$this->fields_list = array(
'id_eqa_category' => array(
'title' => $this->l('ID'),
'align' => 'center',
),
'title' => array(
'title' => $this->l('Title'),
),
);
// Define fields for edit form
$this->fields_form = array(
'input' => array(
array(
'name' => 'title',
'type' => 'text',
'label' => $this->l('Title'),
'desc' => $this->l('Category title.'),
'required' => true,
'lang' => true
),
'submit' => array(
'title' => $this->l('Save'),
)
);
// Call parent constructor
parent::__construct();
}
Other people like to move list and form definitions to actual functions which render them:
public function renderForm()
{
$this->fields_form = array(...);
return parent::renderForm();
}
You don't actually need to do anything else, the controller matches fields to your models, loads them, saves them etc.
Again, the best way to learn about these controller is to look at other AdminControllers.

Pass Radio Button Value Onchange

In Yii, the list view used as a search result.
Controller
public function actionSearch()
{
$key=$_GET['Text'];
$criteria = new CDbCriteria();
$criteria->addSearchCondition('username',$key,true,"OR");
$criteria->select = "`username`,`country`";
$data=new CActiveDataProvider('User',
array('criteria'=>$criteria,'pagination'=>array('pageSize'=>5),
));
$this->render('search', array(
'ModelInstance' => User::model()->findAll($criteria),
'dataProvider'=>$data,
));
}
search.php
<?php
//THE WIDGET WITH ID AND DYNAMICALLY MADE SORTABLEATTRIBUTES PROPERTY
$this->widget('zii.widgets.CListView', array(
'id'=>'user-list',
'dataProvider'=>$dataProvider,
'itemView'=>'results',
'template' => '{sorter}{items}{pager}',
));
?>
<?php echo CHtml::radioButtonList('type','',array(
'1'=>'Personal',
'2'=>'Organization'),array('id'=>'type'),array( 'separator' => "<br/>",'style'=>'display:inline')
);
?>
result.php
<?php echo $data->username."<br>"; ?>
<?php echo $data->country; ?>
The user model fields are id, name , country, type, The search result shows the name and country. Now want to filter the results based on the radio button onchange (personal/organisation).
You could try to use $.fn.yiiListView.update method passing list view's id (user-list in your case) and ajax settings as arguments. data property of ajax settings is what can be used to specify GET-parameters that will be passed to your actionSearch to update the list view. So you have to analyze these parameters in the action and alter CDbCriteria instance depending on them.
The following script to bind onchange handler to your radio button list is to be registered in the view:
Yii::app()->clientScript->registerScript("init-search-radio-button-list", "
$('input[name=\"type\"]').change(function(event) {
var data = {
// your GET-parameters here
}
$.fn.yiiListView.update('user-list', {
'data': data
// another ajax settings if desired
})
});
", CClientScript::POS_READY);
You also may consider the following code as an example based on common technique of filtering CGridView results.
By the way, for performance reasons you can render your view partially in the case of ajax update:
$view = 'search';
$params = array(
'ModelInstance' => User::model()->findAll($criteria),
'dataProvider' => $data
);
if (Yii::app()->request->isAjaxRequest)
$this->renderPartial($view, $params);
else
$this->render($view, $params);

CGridview filter on page load with pre define value in search field

I am working with the Yii framework.
I have set a value in one of my cgridview filter fields using:
Here is my jQuery to assign a value to the searchfield:
$('#gridviewid').find('input[type=text],textarea,select').filter(':visible:first').val('".$_GET['value']."');
And here my PHP for calling the cgridview:
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'bills-grid',
'dataProvider'=>$dataProvider,
'filter'=>$model,
'cssFile'=>Yii::app()->baseUrl . '/css/gridview.css',
'pager'=>array(
'class'=>'AjaxList',
'maxButtonCount'=>25,
'header'=>''
),
'columns' => $dialog->columns(),
'template'=>"<div class=\"tools\">".$dialog->link()." ".CHtml::link($xcel.' Export to excel', array('ExcelAll'))."</div><br />{items}{summary}<div class=\"pager-fix\">{pager}</div>",));
The value appears in the search field and my cgridview works correctly without any issues, but I am unable to trigger the cgridview to refresh or filter. Does anyone know who to trigger the cgridview to filter after page load with a predefined value?
Any help would be greatly appreciated and please let me know if you need additional information.
Thank you.
You can solve the problem without any clientside code modification. In your controller action just set the default value for the attribute as shown below
public function actionAdmin()
{
$model = new Bills();
$model->unsetAttributes();
$model->attribute_name="default filter value";//where attribute_name is the attribute for which you want the default value in the filter search field
if(isset($_GET['Bills'])){
$model->attributes = $_GET['Bills'];
}
$this->render('admin',array('model'=>$model));
}
Have a look at 'default' index action that gii generates:
public function actionIndex()
{
$model = new Bills();
$model->unsetAttributes();
if(isset($_GET['Bills'])){
$model->attributes = $_GET['Bills'];
}
$this->render('index',array('model'=>$model));
}
So if you add one line like: $model->attribute = 'test';, you're done. 'attribute' is of course the attribute that has to have the default filter value (in this case value is 'test') :). So your code looks like:
public function actionIndex()
{
$model = new Bills();
$model->unsetAttributes();
if(isset($_GET['Bills'])){
$model->attributes = $_GET['Bills'];
}
if(!isset($_GET['Bills']['attribute']) {
$model->attribute = 'test';
}
$this->render('index',array('model'=>$model));
}
Of course youre attribute will have a test value (in filter) set up as long as you wont type anything in its filter field. I hope that that's what you're looking for. Your filter should work as always.
Sorry for my bad english :)
Regards
You can use Yii's update:
$.fn.yiiGridView.update('bills-grid', {
type: 'GET',
url: <?php echo Yii::app()->createUrl('controller/action') ?>"?Class[attribute]=<?php echo $_GET['value'] ?>
success: function() {
$.fn.yiiGridView.update('bills-grid');
}
});
This is how i do it, just change the URL, it should be the same controller action of the gridview and change URL parameters to the structure represented in there, should be like Bills[attribute]=value.

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',
)),));