CGridView with CCheckBoxColumn

Here is the scenario - I want to use CGridView with a CCheckBoxColumn to select records - however the checkbox selections need to remain checked whilst I use the paging and filtering functionality of the grid.

Further to this I want to include a dropdown list in one of the columns - and again the selected values need to remain selected.

Is this possible to do in CGridView - if not what would be the best way to do it?

I recommend you to use jQuery.

You could serialize your data before change the page and unserialize after.

You could store them in a hidden field to be able to get them after come back to that point.

I have already done something like that. I had a form generated on-the-fly in a tab. When i sent the data and the validation was failed the form was re-generated on return to the page and my values were lost. I did exactly what i appointed you above to fix that behavior.

Hope it helps.

But how would I do that? The jQuery code is built in to the CGridView so does this mean I need to override it? I need some example code if possible.

In my situation i did the following:

I had used jquery $(’#form_x’).serialize() to get the serialized data and push them into a hidden field on the form. In every reload i had to pull that data from $_POST to a hidden field again and use the data (via jquery) to push them into the propper fields again. Surely you must putt some good logic in that.

I would guess you should do something like that, but maybe easer. Lets suppose you have a list of checks. You could find the propper event in your cgrid (maybe beforeSend) to get the checked ids, put them into a hidden field and load them back on subsequent calls. You would not touch in cgrid scripts if you not wanted. You could use the jquery live() or bind() methods (i guess the first) to get this working. You would have to use Yii::app()->clientScript->registerScript(…) to accomplish it.

I dont know a Yii-way to get this working automatically. If you discover, please, let me know.

Best Regards

Cheers, anybody got any more ideas?

How about getting rid of the paging? you could just add scroll bars to your gridview object so that you would have all of your records at once. This would eliminate the need to request more implicit recurring queries to your database.

This approach requires a bit of jquery and some CSS. I got the idea from:

http://blog.oxagile.com/2009/10/26/scrollable-html-table-with-fixed-header-for-ie-7-ie-8-firefox-35-chrome/

This is just an idea, but if you require paging in your application then this will not work for you.

Regards,

jogasa21 - that is actually a very good idea - put the CGridView in a vertical scrolling DIV, and I have access to all my records on one page. BUT what if I need to use the filters? Then it will just refresh the grid :(

I need a better solution to this…

Perhaps to make it easier, I will explain the scenario in more detail.

Basically I’m trying to create a stock database. There is a Products table that stores the details of hundreds of products. These products are available from specific suppliers; some products are available from more than one supplier, sometimes at different prices. The idea is that when I need to buy new stock, the system will create the shopping list for me (i.e. it will group products by supplier).

So when I need to order new stock I need to be able to search the database and add items to my shopping list. This is why I thought using the checkboxes would be the best solution.

Come to think of it though, checkboxes may not be the best solution. For example I may spend 10 minutes selecting checkboxes and then by accident I click on a link… and all my checkbox selections are gone!

Perhaps the best solution would be to have an AJAX button on each row (add to shopping list) - Clicking this button will add the product to the shopping list table. Once added, the button should be faded so that I know the product is in the shopping list. Clicking the button again will remove the item from the shopping list.

I suppose I could even use checkboxes that instead initiate the AJAX request, rather than being static (but the checkbox status would still need to indicate whether it has been added or not).

What’s the easiest way to do this?

Hmmm… I see, but what is the criteria to select the products from your suppliers?

Is it for the lowest price? if so, it would be easy to achieve by adding another condition to your WHERE clause, so that you don’t need buttons or checkboxes in your gridview. You would just have to take a look to the “automatic order” (shown in the gridview) and approve it or reject it.

If the system is going to create the shopping list for you, this means that you have a "reorder_point" field in your product table to advice you when the quantity of a product is not enough in your stock. However, if you want to establish personal preferences for some suppliers (regardless of the price of their products) then you will need the checkbox in each row.

And yes, you are right. With the filters the gridview is refreshed and the scrollbars will disappear, so to solve this problem I had to refresh the scrollbars as well. I did it with the afterAjaxUpdate option in the CGridView by calling again the javascript function that create the scrollbars. Yes I know… it sucks because it means to have the same code twice, but at least it works for me. I will try to factorize it somehow later.

Regards,

jogasa21 - no you’ve got the wrong idea lol. Basically it is not going to be a “stock control” system - the only purpose of the system is to store product details and supplier prices for those products. Then, when I need to create a shopping list, I manually search for the products I need and add them to a shopping list. The system will then group these products by supplier, i.e. select the cheapest supplier for the products.

But to start off I need an easy way to search/filter products in the CGridView and select the required products to add to the shopping list.

@GStar

How did you end up implementing this? I’m running into a similar problem. My initial idea was to use an ajax link to add users to an email queue but I’m having a hard time getting the ajax link to work inside the CGridView.

Cheers,

Matt

Mate, I ended up doing something totally different, but essentially I am using an AJAX link to make it work. What I would advise you is to implement the AJAX link in a similar way that the "delete" button works in CGridView. So go to your admin page in your browser and view the source - you will find the JS code for the delete function near the bottom. You need to create a code similar to this in your admin.php file.

As an example I did something like this:


Yii::app()->clientScript->registerScript('listupdate', "

$('#product-grid a.listupdate').live('click', function() {

	$.fn.yiiGridView.update('product-grid', {

		type: 'POST',

		url: $(this).attr('href'),

		success: function() {

			$.fn.yiiGridView.update('product-grid');

		}

	});

	return false;

});

");

You will also need to create a controller action that the AJAX link is going to point to to process your request.

Beautiful! Thanks.




<?php

$this->beginWidget('zii.widgets.jui.CJuiDialog', array(

    'id' => 'userloginwidget',

    'cssFile' => 'jquery-ui-1.8.16.custom.css',

    'theme' => 'south-street',

    'themeUrl' => Yii::app()->request->baseUrl . '/css/ui',

    'options' => array(

        'title' => $title,

        'autoOpen' => false,

        'modal' => true,

        'width' => 800,

        'resizable' => false,

    ),

));

?>


<div id="notificationArea">


    <div id="notificationPopup">

        <?php $this->widget('NotificationWidget'); ?>

    </div>


    <?php

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

        'id' => 'notify-grid',

        'dataProvider' => $model,

        'cssFile' => Yii::app()->baseUrl . '/css/gridViewStyle/gridView.css',

        'pager' => array('cssFile' => Yii::app()->baseUrl . '/css/pager.css'),

        'summaryText' => 'Displaying {start}-{end} of {count} record(s)',

        'htmlOptions' => array('class' => 'grid-view'),

        'ajaxUpdate' => 'notificationArea',

        //'updateSelector' => '.notifyLink',

        'template' => '{summary}{items}{pager}',

        'enableSorting' => false,

        'columns' => array(

            'username',

            array(

                'class' => 'CLinkColumn',

                'id' => 'NotifyColumn',

                'linkHtmlOptions' => array(

                    'class' => 'notifyLink',

                ),

                'urlExpression' => 'array("/admin/project/notifyUser", "userId" => $data->id, "projectId" => "' . $projectId . '")',

            ),

        )

    ));


    $this->endWidget('zii.widgets.jui.CJuiDialog');

    ?>


    <?php

    Yii::app()->clientScript->registerScript('NotifyUser', "

        $('#notify-grid a.notifyLink').live('click', function() {

                $.fn.yiiGridView.update('notify-grid', {

                        type: 'POST',

                        url: $(this).attr('href'),

                        success: function(data) {

                            $.fn.yiiGridView.update('notify-grid');

                        }

                });

                return false;

        });

    ");

    ?>

</div>