在 Yii gridview 分页中保留复选框值

Posted

技术标签:

【中文标题】在 Yii gridview 分页中保留复选框值【英文标题】:Retain Checkbox values in Yii gridview pagination 【发布时间】:2012-04-23 09:35:30 【问题描述】:

我有一个 gridview,其中包含一个复选框列,并且还使用分页。当我选中第一页中的一些复选框并导航到第二页并在第二页中选中另一个复选框时,我在第一页中选中的选项不会保留在那里。分页期间是否可以保留复选框值?

Gridview 的代码是

$widget = $this->widget('zii.widgets.grid.CGridView', array(
    'dataProvider'     => $model->search(),
    'cssFile'          => Yii::app()->baseUrl . '/media/js/admin/css/admingridview.css',
    //'filter' => $model,
    'ajaxUpdate'       => true,
    'enablePagination' => true,
    'columns'          => array(
        array(
            'name'   => 'id',
            'header' => '#',
            'value'  => '$this->grid->dataProvider->pagination->currentPage * $this->grid->dataProvider->pagination->pageSize + ($row+1)',
        ),
        array(
            'class'          => 'CCheckBoxColumn',
            'selectableRows' => '2',
            'header' => 'Selected',
        ),
        array(
            'name'   => 'fb_user_id',
            'header' => 'FaceBook Id',
            'value'  => 'Chtml::encode($data->fb_user_id)',
        ),
        array(
            'name'   => 'first_name',
            'header' => 'Name',
            'value'  => 'CHtml::encode($data->first_name)',
        ),
        array(
            'name'   => 'email_id',
            'header' => 'Email',
            'value'  => 'CHtml::encode($data->email_id)',
        ),
        array(
            'name'   => 'demo',
            'type'   => 'raw',
            'header' => "Select",
            'value'  => 'CHtml::checkBox("email[]","",array("class"=>"check","value"=>$data->email_id))',
        ),
    ),
));

编辑:

用于记住gridview中选定选项的扩展,请查看此链接Selgridview

感谢bool.dev

【问题讨论】:

您的复选框是否适用于所有行?我的意思是你为什么不去 CCheckBoxColumn? @bool.dev 我使用了 CCheckBoxColumn,但它也没有用 除了您希望保留复选框状态之外,您可以使用 ccheckboxcolumn 吗?我的意思是除了复选框状态,你能用 ccheckboxcolumn 做所有其他事情吗? @bool.dev 我只是添加 ccheckboxcolumn 和所有其他正常工作的只有 pblm 具有复选框值保留。我在任何这样开发的网站中都找不到 好的..您可以将 CCheckBoxColumn 版本添加到您的问题中吗?只添加修改的部分,也保留旧代码。 【参考方案1】:

您可以使用会话/cookie 来存储检查的值。我不太确定如何使 cookie 工作,所以我会告诉你如何使用会话来做到这一点。特别是 yii 创建的用户会话。

现在要使用会话,我们需要将已检查(和未检查)的 id 传递给控制器​​,因此我们将在每次 ajax 更新(即分页之间)时修改发送到控制器的数据,为此我们利用beforeAjaxUpdate CGridView 的选项。

我也在你的代码中使用CCheckBoxColumn而不是以下代码(当然你可以修改解决方案以满足你自己的需要):

array(
     'name' => 'demo',
     'type'=>'raw',
     'header' => "Select",
     'value' => 'CHtml::checkBox("email[]","",array("class"=>"check","value"=>$data->email_id))',
),

GridView 变化:

<?php $this->widget('zii.widgets.grid.CGridView', array(
    // added id of grid-view for use with $.fn.yiiGridView.getChecked(containerID,columnID)
    'id'=>'first-grid',

    'dataProvider'=>$model->search(),
    'cssFile' => Yii::app()->baseUrl . '/media/js/admin/css/admingridview.css',

    // added this piece of code
    'beforeAjaxUpdate'=>'function(id,options)options.data=checkedIds:$.fn.yiiGridView.getChecked("first-grid","someChecks").toString(),
        uncheckedIds:getUncheckeds();
        return true;',

    'ajaxUpdate'=>true,
    'enablePagination' => true,
    'columns' => array(
            array(
                 'name' => 'id',
                 'header' => '#',
                 'value' => '$this->grid->dataProvider->pagination->currentPage * $this->grid->dataProvider->pagination->pageSize + ($row+1)',
            ),
            array(
                 'name' => 'fb_user_id',
                 'header' => 'FaceBook Id',
                 'value' => 'CHtml::encode($data->fb_user_id)',
            ),
            array(
                 'name' => 'first_name',
                 'header' => 'Name',
                 'value' => 'CHtml::encode($data->first_name)',
            ),
            array(
                 'name' => 'email_id',
                 'header' => 'Email',
                 'value' => 'CHtml::encode($data->email_id)',
            ),

            /* replaced the following with CCheckBoxColumn
              array(
                 'name' => 'demo',
                 'type'=>'raw',
                 'header' => "Select",
                 'value' =>'CHtml::checkBox("email[]","",array("class"=>"check","value"=>$data->email_id))',
              ),
            */

            array(
                 'class' => 'CCheckBoxColumn',
                 'selectableRows' => '2',
                 'header'=>'Selected',
                 'id'=>'someChecks', // need this id for use with $.fn.yiiGridView.getChecked(containerID,columnID)
                 'checked'=>'Yii::app()->user->getState($data->email_id)', // we are using the user session variable to store the checked row values, also considering here that email_ids are unique for your app, it would be best to use any field that is unique in the table
            ),
    ),
));
?>

特别注意beforeAjaxUpdate 和 CCheckBoxColumn 的代码,在 beforeAjaxUpdate 中,我们将 checkedIds 作为已检查的所有 id(在本例中为 email_ids)的 csv 字符串传递,uncheckedIds 作为 csv 字符串传递在所有未选中的 id 中,我们通过调用函数getUncheckeds() 来获取未选中的框,该函数很快就会出现。请注意,当我在测试时,我使用了一个整数 id 字段(我的表)作为唯一字段,而不是电子邮件字段。

getUncheckeds() 函数可以像这样在 gridview 的视图文件中的任何位置注册:

Yii::app()->clientScript->registerScript('getUnchecked', "
       function getUncheckeds()
            var unch = [];
            /*corrected typo: $('[name^=someChec]') => $('[name^=someChecks]') */
            $('[name^=someChecks]').not(':checked,[name$=all]').each(function()unch.push($(this).val()););
            return unch.toString();
       
       "
);

在上面的函数中注意选择器和eachpush函数。

完成后,我们需要修改此视图的控制器/动作。

public function actionShowGrid()
     // some code already existing
     // additional code follows
     if(isset($_GET['checkedIds']))
          $chkArray=explode(",", $_GET['checkedIds']);
          foreach ($chkArray as $arow)
               Yii::app()->user->setState($arow,1);
          
     
     if(isset($_GET['uncheckedIds']))
          $unchkArray=explode(",", $_GET['uncheckedIds']);
          foreach ($unchkArray as $arownon)
               Yii::app()->user->setState($arownon,0);
          
     
     // rest of the code namely render()

就是这样,它现在应该可以工作了。

【讨论】:

非常感谢..会检查...感谢您耐心找出解决方案.. 不客气,下次在这么大的问题上给予赏金:)。我确实说过,我会尝试,所以我做到了。无论如何,请记住要点,sessions/cookiesbeforeAjaxUpdatesetState() getState() 函数。如果您愿意,您可以将内容存储在单独的会话变量而不是用户会话中。 另外,除了isset,您可能还想检查empty 当然...感谢您的大力支持。 还有一个我今天遇到的扩展,可能会有所帮助:selgridview【参考方案2】:

要开发该方案,您需要了解导航时发生的情况。

当您导航到分页页面时,会进行 ajax 调用并接收到新数据,并从 CActive Record 或任何数据源中获取数据。新数据是根据数据库记录或源记录。当您再次返回上一页时,将进行 Ajax 调用并更新内容,因此与数据库中的内容相同。

我觉得你应该暂时保存检查项目的数据,如果采取行动,则将其永久保存。

你可以这样做

<script type="text/javascript">
$("input:checkbox").click(function () 
    var thisCheck = $(this);
    if (thisCheck.is (':checked'))
        // do what you want here, the way to access the text is using the
        // $(this) selector. The following code would output pop up message with
        // the selected checkbox text
        $(this).val());
    
);
</script>

你可以在某处保存临时存储

【讨论】:

感谢您的回复..您可以提供任何示例吗? 您是否勾选了数据库字段?【参考方案3】:

也可以在普通表单提交上进行这项工作:

我想将此添加为对 bool.dev 答案的评论,但我还没有足够的声誉来做到这一点。所以我不得不把它放在一个单独的答案中。

bool.dev,你的回答很棒,而且效果很好,thanx。

但是,正如预期的那样,它仅在 ajax 调用更新 gridview 时才有效。我有 gridview 构成表单的一部分,所以我希望它也可以正常提交表单,否则当表单上存在其他验证错误时,不会再次加载复选框。

因此,除了您所做的之外,我还在表单上添加了隐藏字段,例如:

<input type="hidden" name='checkedBox1' id='checkedBox1' value=''>
<input type="hidden" name='uncheckedBox1' id='uncheckedBox1' value=''>

然后,在提交表单之前,我的 sumbit 按钮会运行您的 getChecked() 和 getUncheckeds() 函数并将其结果存储在隐藏字段中:

if ($('#checkedBox1').length >0)   $('[name=checkedBox1]').val(getChecked());
if ($('#uncheckedBox1').length >0) $('[name=uncheckedBox1]').val(getUncheckeds());

在控制器中,除了检查 $_GET['checkedIds'] 之外,您还检查 $_POST['checkedBox1'] 并将其值存储到会话中,就像检查 $_GET['checkedIds'] ,使用相同的会话变量。

对 $_POST['uncheckedBox1'] 执行相同操作。

应该可以的。

【讨论】:

以上是关于在 Yii gridview 分页中保留复选框值的主要内容,如果未能解决你的问题,请参考以下文章

在Yii2 gridview中禁用分页

C# 分页中 CodeBehind 的 GridView 不起作用

yii2 gridview 怎么加checkbox

ASP.NET MVC中使用MvcPager异步分页+在分页中复选框下一页上一页也保持选中

ASP:带有分页的 Gridview 复选框列未显示选中了哪个复选框

如何将数据表分页中的记录发送到服务器类