SelGridView extends CGridView with following features:
- remember selected rows on sorting / paging grid
- select rows programmatically by GET param (e.g. to highlight new record, etc)
Demo ¶
Download ¶
Requirements ¶
Tested on Yii 1.1.9.
Installation ¶
Put selgridview folder from zip to your protected/extensions.
Usage ¶
Use as standart CGridView widget (don't forget to set selectableRows >= 1).
Controller:
public function actionIndex()
{
$dataProvider = new CActiveDataProvider('User', array(
'pagination' => array(
'pageSize' => 2,
),
));
$this->render('index', compact('dataProvider'));
}
View index.php:
<?
$this->widget('ext.selgridview.SelGridView', array(
'id' => 'mygrid',
'dataProvider' => $dataProvider,
'selectableRows' => 2,
'columns'=>array(
array(
'class' => 'CCheckBoxColumn',
),
'UserID',
'UserName',
),
));
?>
When sorting or paging such grid, you will see in ajax GET params "User_sel={id}" as well as "User_page={page}". Value of User_sel is model primaryKey. Widget automatically proceess this value and select rows.
If you want to highlight newly created row in grid you need to set GET param User_sel={new-record-id}:
$this->createUrl('user/index', array('User_sel' => 123));
To get all selected keys on all pages in your javascript (when selectableRows >= 2): ~~~ [javascript] var selected = $("#mygrid").selGridView("getAllSelection"); ~~~
Usage with bootstrap ¶
it is possible to use with bootstrap gridview.
Example:
$this->widget('ext.selgridview.BootSelGridView', array(
'id' => 'mygrid',
'dataProvider' => $dataProvider,
...
To highlight selected rows in such bootstrap-grid you can add to your css: ~~~ [css] table.table tr.selected td, table.table tr.selected:hover td {
background: none repeat scroll 0 0 #BCE774;
} ~~~
How it works ¶
Standart CGridView can automatically select rows in grid when there is checkox column with checked = true values. But it does not keep selection on sorting / paging. This extension makes two things:
- creates hidden CCheckBoxColumn that gets checked by GET param. If there is checkbox column in widget config, no hidden column generated
- attach BeforeAjaxUpdate js function that adds GET params to URL when sorting and pagination
Note ¶
When you have selectableRows > 1 SelGridview will remember all selected rows on all grid pages not only on visible page.
Issues ¶
Please submit issues to github. Thanks for feedback!
History ¶
Mar 21, 2012
Added support of BootGridView
Mar 18, 2012 (version 2.0)
- widget significally rewriten with javascript, code became more clear
- added JS method for getting all selected keys from all pages (comment #7371)
Mar 16, 2012
Feb 25, 2012
Added support of CArrayDataProvider
Feb 24, 2012
Initial release
a small change
when exist CCheckBoxColumn and use 'selectableRows'>1,not work fine.
see the change in
http://www.yiiframework.com/forum/index.php/topic/29842-cgridview-selectable-keeping-selection
and work fine
fixed #7346
Thank you horacio, fixed!
Catch Only Current Page
Hai vitalets, thaks for your extension..
I use checkbox in my apps... The rows success for select in other page.. but when i want catch with submit action, i just get the row in current page..
I use 'selectableRows'=>2, if i use selectableRows=>1 that cant do multi select in checkbox.. this is my code in view :
$this->widget('application.extensions.SelGridView', array( 'dataProvider'=>$model->search(), 'selectableRows'=>2, 'columns'=>array( array( 'class'=>'CCheckBoxColumn', 'id'=>'haha', ),
And i get value select in controller like this :
if(isset($_POST['haha'])) { foreach($_POST['haha'] as $a=>$val) { }
i catch the "haha" POST..
How can i solve my problem? thanks...
Re: Catch Only Current Page
see this http://www.yiiframework.com/forum/index.php/topic/29842-cgridview-selectable-keeping-selection/pageviewfindpostp143768
my poor solution
New version released, everything fixed
Hi all
everything fixed in new 2.0 version.
Thanks for your ideas!
problem
Not work for me, not keep the selection when use
'selectableRows'=>2,
:(
need suggestion ! when we use some other GridView and cann't extend the CGridView
if we use some other GridView extension what should we do ?
for example if we use the BootGridView and need this functionality ,what 's the best options ? copy the code of your extension to the new version ? lets say:
MyGridView extends BootGridView{ /* do the same as your extension ?? here */ }
Answers
Hi Horacio!
$this->widget('ext.selgridview.SelGridView', array(...
hi yiqing95,
it's the common problem when you have two widgets and want to keep both in one.
Solution is to extend SelGridView from BootGridView - you can fix it in extensions/selgridview/SelGridView.php. I hope it will work :) But in long perspective it is not good: if I release new version and you decide to update and forget to fix SelGridView.php it may cause errors.
Another option is as you suggested to create your own grid extending BootGridView and copy-paste code from SelGridView, but here you should take care about assets (jquery.selgridview.js)!
The best solution is to make special bootstrap version of SelGridView. I think I will do it in a few days as I consider bootstrap components very nice and useful:)
Problem
hai vitalets, thaks for your update..
But its not work for me too.. i use the update extension but that not save selected value if i change my page.. And when i change page, that load new page(ajax not work)..
thanks..
add more detailed usage
hi sabitzhabit,
I've added the simplest controller and view in Usage that works for me.
Could you have a look and compare with your code.
And if still not working could you provide your code?
Hope this helps!
Bug
//thanks to Horacio Segura http://www.yiiframework.com/extension/selgridview/#c7346 foreach($this->columns as $col) { if($col instanceof CCheckBoxColumn) { $col->checked = $checkedExpression; $col->init(); return; } }
SelGridView.php Line 66.
I just want to notice, that this patch is not a good idea.
When user already have CCheckBox column AND checked property defined - this code overrides user-defined checked property and checkboxes never will be checked. I think there is some other fix needed.
about user's CCheckBoxColumn
hi vitman,
thanks for your notice. As I understand when your have own CCheckBoxColumn with value taken from db there is no need to use SelGridView. Because selected rows (= checked) are loaded from db each time grid is updated.
I mainly use this extension for highlight particular row (e.g. to show user which row he just worked on)
Please correct me if I'm wrong.
about user's CCheckBoxColumn
vitalets
As i uderstand, main idea of this selgrid - that user can check\uncheck rows on different pages and selection will be saved. Thats OK.
In my case, i need to show grid to user, with many rows(so grid paginated and rendered via ajax) - AND user should check some rows. But later - user may change his decision(edit), so i need to show this grid again and previously checked rows should be checked, then again selected checkboxes on all grid pages should be saved - so i defined checked property to check already saved checkboxes. But it didnt work because grid has overloaded checked property and dont use my own.
Hope you will understand me right.
As a Behavior
Hi
There are several extensions around modifying the 'CGridView', for instance 'EExcelView', but that is not the only one.
So I tried to map this to a Behavior. Unfortunately, there are not enough event hooks in Yii to make that completely possible.
Yet, I did something that is 'close'.
Usage:
$grid=$this->createWidget('...CGridView',... $gridsel=$grid->attachBehavior( 'SelGridViewBehavior',array( 'class'=>'ext.SelGridView.SelGridViewBehavior', ) ); $grid->run(); $gridsel->run();
And transformed 'SelGridView' into 'SelGridViewBehavior extends CBehavior'. I replaced certain references to '$this' with '$this->owner'.
And I created 'attach':
public function attach($owner) { parent::attach($owner); $this->init(); $this->initColumns(); }
'createWidget' already did the 'init' and 'initColumns' of the CGridView, so the 'attach' is doing the same for the behavior.
The javascript must be registered after the javascript for 'CGridView', this is done in
public function run() { $this->registerClientScript(); }
Not an ideal implementation, but flexible enough to use several extensions already around.
As a CGridColumn
Hi
I converted this into a column so that it can be added to any CGridView kind and so that adding the checkbox column does not conflict with other checkboxcolumns.
The code is at SelGridColumn class.
and used like this:
$columns=array( array('class'=>'ext.SelGridView.SelGridColumn'), array('name'=>'displayname_search', 'value'=>'$data->displayname', ), ),
with the possibility to set some options:
$columns=array( array( 'class'=>'ext.SelGridView.SelGridColumn', 'selVar'=>'blabla', 'selBaseScriptUrl'=>'blabla', 'hidden'=>true, /* to hide the column rather than show it */ ), ),
I have updated the SelGridView class to use this new Column class instead SelGridView class using SelGridColumn and I think that this can be similar for BootSelGridView which avoids code duplication.
RE: As a Behavior or column
hi le_top,
I've thought about exactly this problem. I don't see now convenient way in Yii 1.1 to combine several extensions of one widget. My realization based on Behavior was also dirty.
Now I think the best way is to create separate widget that takes orignal widget id as parameter.
for example:
//standart CGridView $this->widget('CGridView', array( 'id' => 'mygrid', )); //appending SelGridView functionality $this->createWidget('ext.selgridview.SelGridView', array( 'gridId' => 'mygrid', ));
but this approach should to be re-checked.
I've created message in related feature request
? Grid Column implementation / Idea to extend library classes with behaviours.
vitalets, what do you think about the implementation as a Grid Column. I think it is pretty nice - not 'ideal', but fits the purpose.
To make classes easily extendable, the public methods should not be implemented as real methods, but all require to go through '_call'. In some cases, this may not be preferable for performance reasons, but that may just be exceptions.
So a public (library) method should be for instance
public function _run() { blabla(); }
Then, when calling 'run', the 'call' method would be checked to lookup the actual method because it is missing initially. At that time the 'call' method could look it up in the behaviors.
RE: ? Grid Column implementation
hi le_top,
Implementation as grid columns is truly better than current as it gives more flexibility.
In common we are lucky that CGridView has columns that can be extended. And we can change grid behavior via column. With other widgets this approach will not work.
It really would be great to have widget behaviors and code will look like:
$this->widget('CGridView', array( 'dataProvider'=>$model->search(), 'selectableRows'=>2, 'behaviors' => array( 'SelGridView' => array( 'class' => 'ext.selgridview.SelBehavior' ), 'GroupGridView' => array( 'class' => 'ext.groupgridview.GroupBehavior' ), ),
As far as I know such feature is not planned for Yii now.
"Refresh" the selected items
First of all, thanks for such a great extension.
For example, I have items model, with ids : 1, 2, 3, 4. I select 2 items of them, eg: 2 and 4. After I click the special delete button, it produces an ajax request, delete item 2 and 4. Then after a success deletion, I refresh the ccgridview.
[javascript] success: (function (e){ //we refresh the CCGridView after success deletion $.fn.yiiGridView.update("items-grid");
Everything's running nicely. But if I want to delete another item, eg: item with id 1, then the selected items consists of 3 items (1, 2, and 4) because it still remember the previous deleted items. To refresh the extension and start from the very beginning, I use this
[javascript] $("#items-grid").selGridView("init");
Do you have any other better solution? Thank you.
Re: "Refresh" the selected items
hi,
please try this:
~~~
[javascript]
$("#items-grid").selGridView("clearAllSelection");
~~~
HTH
Re: "Refresh" the selected items
[javascript] $("#items-grid").selGridView("clearAllSelection");
It doesn't work (since there is no such a method named clearAllSelection)
Re: "Refresh" the selected items
omg, I'am surprised that version here is older than my local copy.
I've created github repo, please try the latest version.
It has
clearAllSelection
method and should do the job.How to get all selected keys in the controller
var selected = $("#mygrid").selGridView("getAllSelection");
How to submit "var selected" to controller for further processing
thx
Re: How to get all selected keys in the controller
I don't know the best practice, but I did it like this..
[javascript] var selected = $("#items-grid").selGridView("getAllSelection"); //if nothing's selected if ( ! selected.length) { alert('Please select minimum one item to be deleted'); return false; } //confirmed? if ( ! confirm('Are you sure to delete ' + selected.length + ' items?')) return false; var multipledeleteUrl = "<?php echo Yii::app()->baseUrl;?>/items/multipledelete"; $.ajax({ type: "POST", url: multipledeleteUrl, data: {selectedItems : selected}, success: (function (e){ //we refresh the CCGridView after success deletion $.fn.yiiGridView.update("items-grid"); //just to make sure we delete the last selected items $("#items-grid").selGridView("clearAllSelection"); }) });
On your items controller, on actionMultipleDelete()..
//..... $selectedItems = Yii::app()->request->getPost('selectedItems'); //iterate through all ids foreach ($selectedItems as $id) { //do your action here.... }
submitting selected trhough ajax - example 2
Or you can do something like this if you'ld like Yii to generate your code (CSRF may need to be added here);
$jsData=<<<EOJS { 'YourModel[field]': jQuery('#{$grid->id}').selGridView('getAllSelection').join() } EOJS; echo CHtml::ajaxButton( 'send','', array('data'=>"js:$jsData",) );
I can't save my form.
Good afternoon.
I have a form with a textfield and a selgridview.
I can't save my values for textfield aand selgrdiview.
<script> $("body").on("click","#submitMedicamento",function(){ var selected = $("#to-pactivos-grid").selGridView("getAllSelection"); //if nothing's selected if ( ! selected.length) { alert('Please select minimum one item to be deleted'); return false; } $.ajax({ type: "POST", url: "<?php echo Yii::app()->createUrl('toMedicamentos/create'); ?>", data: {selectedItems : selected}, success: (function (data){ //document.getElementById('to-medicamentos-form').submit(); }), error: function(data) { // if error occured alert("Error occured.please try again"); alert(data); }, dataType:'html' }); return false; }); </script>
echo CHtml::submitButton( $modelMedicamentos->isNewRecord ? 'Alta' : 'Actualizar', array('id'=>'submitMedicamento') );
Can anyone help me?
Tanks.
Re: Selected items on another page are not saved.
hi, please check:
selectableRows = 2
in grid config ?Vitalets, I edit my post.
Please, view my post again.
SelectableRows is OK.
I have AJAX pagination, I think.
Re: Vitalets, I edit my post.
lagogz, for me everything looks correct.
$("#to-pactivos-grid").selGridView("getAllSelection")
to see what is actually returned?
Here my code!
views/toMedicamentos/_form.php
<script> $("body").on("click","#submitMedicamento",function(){ var selected = $("#to-pactivos-grid").selGridView("getAllSelection"); //if nothing's selected if ( ! selected.length) { alert('Please select minimum one item to be deleted'); return false; } $.ajax({ type: "POST", url: "<?php echo Yii::app()->createUrl('toMedicamentos/create'); ?>", data: {selectedItems : selected}, success: (function (data){ }), error: function(data) { // if error occured alert("Error occured.please try again"); alert(data); }, dataType:'html' }); return false; }); </script> ... <div class="form"> ... <?php $form=$this->beginWidget('CActiveForm', array( 'id'=>'to-medicamentos-form', 'enableAjaxValidation'=>false, )); ?> ... <div class="row"> <?php echo $form->labelEx($modelMedicamentos,'Medicamento'); ?> <?php echo $form->textField($modelMedicamentos,'Medicamento',array ('size'=>60,'maxlength'=>64)); ?> <?php echo $form->error($modelMedicamentos,'medicamento'); ?> </div> ... <div class="textaligncenter"> <?php $this->widget('application.components.SelGridViewGal', array( 'id'=>'to-pactivos-grid', 'dataProvider'=>$modelPActivos->search(), 'filter'=>$modelPActivos, 'selectableRows' => 2, 'columns'=>array( array( 'class' => 'CCheckBoxColumn' ), 'Principio_Activo', array( 'class'=>'CButtonColumn', ), ), )); ... </div> <div id="shortBottomBar"> <?php echo CHtml::submitButton( $modelMedicamentos->isNewRecord ? 'Alta' : 'Actualizar', array('id'=>'submitMedicamento') ); ?> </div> </div> <?php $this->endWidget(); ?>
ToMedicamentosController.php__
public function actionCreate() { ... if(isset($_POST['ToMedicamentos'])) { ... if(isset($_POST['selectedItems'])) { foreach ($_POST['selectedItems']as $IdPrincipio_Activo) { $this->linkChildRecord($IdMedicamento, $IdPrincipio_Activo); } } ... }
When I press submit button, I want to send $_POST['selectedItems'] and $_POST['ToMedicamentos'] to create action on my controller.
With this code, if I do an "alert(selected [0]);" in my AJAX code, I can show it, but no actionCreate is launched.
Thanks for reply.
Re: Here my code!
maybe textfield value missing in ajax data?
~~~
[javascript]
$.ajax({
type: "POST",
url: "<?php echo Yii::app()->createUrl('toMedicamentos/create'); ?>",
data: {selectedItems : selected, ToMedicamentos: $('#Medicamento').val()},
...
~~~
Anyway, if you see correct
alert(selected.length)
it's not a selgridview issue, try to comment all selgridview parts and submit textfireld only.hth
I still have the problem.
Good morning.
The problem is AJAX post, no SelGridView.
With the code as I have the actionCreate isn't launched.
If I put
'enableAjaxValidation'=>true,
in CActiveForm configuration, ToMedicamentos data is saved but no data from the SelGridView.
Could it be that I have to put a button type different from submitButton?
I don't understand why it fails.
Thanks.
PD.:
Here is my ToMedicamentos/actionCreate:
public function actionCreate() { $modelMedicamentos=new ToMedicamentos; $IdMedicamento=0; $modelPActivos=new ToPrincipiosActivos; $modelMPA = new TvPactivosMedicamentos("searchIncludingPActivos($IdMedicamento)"); $modelMPA->unsetAttributes(); $modelMPA->scenario = 'searchIncludingPActivos'; if(isset($_POST['ToMedicamentos'])) { $modelMedicamentos->attributes=$_POST['ToMedicamentos']; if($modelMedicamentos->save())/* Save the Role model */ { $IdMedicamento = $modelMedicamentos->IdMedicamento; $modelito=new ToMedicamentos; $modelito->Medicamento='jajejijoju'; $modelito->save(); $modelMPA = new TvPactivosMedicamentos(); $modelMPA->IdMedicamento = $IdMedicamento; $modelMPA->IdPrincipio_Activo = 12; $modelMPA->save(); $selectedItems=Yii::app()->request->getPost('selectedItems'); foreach ($selectedItems as $IdPrincipio_Activo) { $this->linkChildRecord($IdMedicamento, $IdPrincipio_Activo); } $this->redirect(array('view','id'=>$IdMedicamento)); } } $this->render('create',array( 'modelMedicamentos'=>$modelMedicamentos, 'modelMPA'=>$modelMPA, 'modelPActivos'=>$modelPActivos, 'IdMedicamento' => $IdMedicamento, )); }
Notice that I created one new ToMedicamentos model called $modelito and one TvPactivosMedicamentos called $modelMPA. When I press submitButton, $modelMedicamentos ,$modelito and $modelMPA are saved in database, but
$selectedItems=Yii::app()->request->getPost('selectedItems'); foreach ($selectedItems as $IdPrincipio_Activo) { $this->linkChildRecord($IdMedicamento, $IdPrincipio_Activo); }
doesn't work.
selectedItems and ToMedicamentos sent by AJAX are empty. That is, AJAX does not send data. Why?
Furthermore,
$this->redirect(array('view','id'=>$IdMedicamento));
Doesn't work.
Re: I still have the problem.
answered in PM.
Ability to uncheck all?
Hey, I really love this plugin to remember the checkboxes, however, is there a way to unselect them all and "forget" what was checked?
Re: Ability to uncheck all?
yes:
$("#grid2").selGridView("clearAllSelection");
Thanks
Ah.. I had version 2.0 of this extension, no wonder I could not see that method in the JS. Thanks.
The clearing selection
Hey, I noticed that when I use selGridView("clearAllSelection"), the checkboxes of the current page are unchecked, but the other pages with checkboxes checked do not get unchecked. Is that a bug?
Re: The clearing selection
hi, yes it was a bug.
Fixed in 2.3 version. Thanks!
Problem when working with a form
Hi,
I have a form and a table in it.
If I select a row, and then move to the next page (so that the selected row can't be seen), and then press on the submit button, I get nothing in the selected rows.
Note that:
Thanks,
Zvi.
Zvi, I do the following
Good morning all!
Suppose I have 3 tables:
Authors: AuthorId, Name
Books: BookId, Title
Authors_Books: AuthorId, BookId
A book can have multiple authors.
Then, when I add a new book, I want to select multiple authors in SelGridView and save data.
model Books
public $Authors; //I build this property that have authors ids separated by commas. ... public function rules() { // NOTE: you should only define rules for those attributes that // will receive user inputs. return array( array('Authors', 'required'), ...
Books _form.php
<script> function selAuthors() { var arraySel = $("#to-authors-grid").selGridView("getAllSelection"); var stringSel=arraySel.join(','); $('#Books_Authors').val(stringSel);//#Books_Authors is hidden field id. } ..... //This hidden field will have authors ids separated by commas. <div class="row"> <?php echo $form->hiddenField($modelBooks,'Authors'); echo $form->error($modelBooks,'Authors'); ?> </div> //in SelGridView widget. ... 'selectionChanged'=>'js:selAuthors', ...
Books controller, in actionCreate:
$Authors=explode(',',$modelBooks->Authors);//Make an authors array. foreach ($Authors as $IdAuthor) //Save relation data. }
I hope it will be helpful.
lagogz, thank you very much
Works like charm :-)
I'm very pleased
It's great that the code works for you.
Regards.
Awesome extension !!!!
Really Good extension with very detailed description.
Thanks!
Great extension, Vitalets.
It works very well :)
How do I submit all selected rows?
How do I submit all selected rows from different pages? I have found it's only submitting selected rows from active page. In browser console I have found it's generating URL with all selected rows.
Is there any way that can help me to submit form with all selected rows from different pages?
Thanks in advance
nice work...a suggestion
Heyy! nice work there..just to add up, you could change line 40 of SelGridView.php to;
$this->selBaseScriptUrl = Yii::app()->getAssetManager()->publish(dirname(__FILE__).'/assets');
in order to allow placing the extension somewhere else aside protected/extensions folder.
For e.g, i have frontend, common and backend as my folder structure and i placed extension inside common, it threw error of not able to locate the assets folder.
Hope this helps -:)
Unable to select more than 300 contacts
Hi,
I am facing an issue as I am not able to select more than 300 records due to $_GET parameter limit. So if there are any method by which I can select as many contacts as per requirment.
Disable rows
I use this extension and I'm happy with it.
The only thing I wish I have is that it's possible to exclude rows from selection. I have added a checkbox for every row, but even when I make it 'disabled', it's still possible to select it when I tick the row or the checkbox in the header column.
'columns'=>array( array( 'class' => 'CCheckBoxColumn', 'disabled'=>'$data->finished==0?"":"disabled"', ),
Is it limitied to 98 rows?
The extension is working great.
BUT , I have 220 rows , and selGrid is saving only up to 98.
Does it have to do something with the URL's length?
Thank you very much.
it's work very well for me.
URL Rewrite
My GET parameters are being rewritten so I'm getting a "Forbidden" error:
http://my.website.com/model/update/Model_sel[0]/4/Model_sel[1]/43/Model_sel[2]/792/ajax/model-grid/id/10/Model_page/3?Model_sel[]=4&Model_sel[]=43&ajax=model-grid
Any tips on excluding this URL from URL rewrite rules?
URL rewrite
Hi
The issue is beyond 'selgridview's code.
I reported this behavior on the forums:
http://www.yiiframework.com/forum/index.php/topic/61761-yii-11-cgridview-curlmanager-breaks-filtering/
I am not reporting anything as a bug anymore as in +95% of the cases they are not considered as bugs. So I just report a behavior - up to the reader to decide if it merits a change or not.
I plan on digging into a specialisation for my use cases - when I find enough time. A first method could be to detect that '_page' is amongst the parameters and avoid the rewriterule in that case.
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.