2

我在 Yii 中有一个视图,即“Patients”视图,它有许多 CGridView 和其他在加载初始视图后加载的 ajax 元素。有些是在已经加载 ajax 的 div 中加载的 ajax,这意味着它们嵌套了 2 层。

在这些 ajax 加载的 CGridViews 中,我有下拉菜单,让用户可以设置每个网格中每页的结果数。这可以正常工作,直到用户使用 ajax 在页面上加载另一个元素。在 ajax 加载另一个网格(或其他任何东西)之后,它会破坏每个页面 ajax 函数的所有其他结果,除了刚刚加载的那个。

使用 ajax 加载任何其他内容后,其他 CGridViews 将在使用我的每页结果下拉列表时抛出此 javascript 错误:

类型错误:设置未定义

内置的 CGridView 分页器始终适用于所有网格,所以我知道必须有某种方法让我的每个页面选择器的结果找到正确的 $.fn.yiiGridView 进行更新。

加载 cgridview 内联的控制器操作:

public function actionInlineSearch()
{
   YiiSessions::model()->setFromRequestCookie();

    $model=new GeneExpressionCufflinksGene('search');
    $model->unsetAttributes();  // clear any default values 
    // page size drop down changed

    if (isset($_GET['gecgPageSize'])) {
        Yii::app()->user->setState('gecgPageSize',(int)$_GET['gecgPageSize']);
        unset($_GET['gecgPageSize']);  // would interfere with pager and repetitive page size change
    }
    $gecgPageSize=Yii::app()->user->getState('gecgPageSize');

    if(isset($_REQUEST['GeneExpressionCufflinksGene']))
        $model->attributes=$_REQUEST['GeneExpressionCufflinksGene'];

    $this->renderPartial('inlineSearch',array('model'=>$model,'gecgPageSize'=>$gecgPageSize), false, true);
}

加载 CGridView 小部件的 inlineSearch 视图:

 // $columns[]='normal_allele_depth';
// $columns[]='normal_allele_freq';

echo "<div class='results-selector'>";
echo "Results per page: ". 
    CHtml::dropDownList('gecgPageSize',$gecgPageSize,array(10=>10,20=>20,50=>50,100=>100),array(
        'onchange'=>"
            $.fn.yiiGridView.update('gecg',{ data:{gecgPageSize: $(this).val() }});
        ",
    ));
echo "</div>";

$this->widget('zii.widgets.grid.CGridView', array(
   'id'=>'gecg',
   'filter'=>$model,
   'dataProvider'=>$dataProvider, 
   'columns'=>$columns,
));
?>

想法?

4

2 回答 2

0

我不确定我是否得到了您所写的所有内容,但是您对两次深度加载CGridView的寻呼机的工作有信心吗?

Yii使用 jQuery 的.on()方法将事件处理程序附加到寻呼机的按钮、排序按钮、CButtonColumn类的按钮。如果您指定参数,则将触发所有匹配的 jQuery 元素方法的后代事件,无论是在此调用时存在的还是不存在的。selectoron()

Yii 将处理程序附加到document页面上始终存在(并且必须存在以允许触发事件)的元素。CGridView您可以将其视为'sinit方法中的示例zii/widgets/assets/gridview/jquery.yiigridview.js

settings.updateSelector = settings.updateSelector
    .replace('{page}', pagerSelector)
    .replace('{sort}', sortSelector);

gridSettings[id] = settings;

if (settings.ajaxUpdate.length > 0) {
    $(document).on('click.yiiGridView', settings.updateSelector, function () {
        // Check to see if History.js is enabled for our Browser
        if (settings.enableHistory && window.History.enabled) {
            // ...
        } else {
            $('#' + id).yiiGridView('update', {url: $(this).attr('href')});
        }
        return false;
    });
}

因此,我想如果您CGridView在 ajax 请求上呈现小部件,那么寻呼机、排序等的所有事件处理程序都将附加到documentajax 页面的部分呈现元素,但不会附加到新加载的元素所属的主页之一。如果您inlineSearch通过 ajax 加载视图,下拉列表可能会发生同样的事情。

这就是为什么,正如我所见,所有事件处理程序都必须附加到document最初加载页面的主非 ajax 视图的元素上。

于 2012-11-15T15:38:16.043 回答
0

解决方案:经过一番折腾后,我决定在每个 inlineSearch 视图的末尾手动将settings+存储$.fn.yiiGridView在一个窗口变量中,然后在我的每页选择器项目发生更改时从窗口中检索它们。

这不是一个非常优雅的解决方案(特别是因为寻呼机工作正常,它会导致多个 $.fn.yiiGridView 实例浮动)但是很好。它可以工作,虽然我在 Yii 上还是个菜鸟,但我可以通过我的研究表明,多个 ajax 加载的小部件存在一些未解决的问题。

inlineSearch 视图中每个页面元素的新结果:

echo "<div class='results-selector'>";
echo "Results per page: ". 
    CHtml::dropDownList('gecgPageSize',$gecgPageSize,array(10=>10,20=>20,50=>50,100=>100),array(
        'onchange'=>"
            $.fn.yiiGridView=window.gecgGridView; // necessary in case other other ajax load doesn't have the yiigridview js
            $.fn.yiiGridView.settings['gecg']=window.gecgGridSettings; // because it will have been clobbered by other ajax grid load
            $.fn.yiiGridView.update('gecg',{ data:{ gecgPageSize: $(this).val() }});
        ",
    ));
echo "</div>";

在 inlineSearch 视图的末尾,这保存settingswindow

<script type='text/javascript'>
$(function(){ 
    window.gecgGridView=$.fn.yiiGridView;
    window.gecgGridSettings={
                            ajaxUpdate:["gecg"],
                            ajaxVar:"ajax",
                            pagerClass:"pager",
                            filterClass:"filters",
                            loadingClass:"grid-view-loading",
                            pageVar:"GeneExpressionCufflinksGene_page",
                            pagerClass:"GeneExpressionCufflinksGene_page",
                            selectableRows:1,
                            tableClass:"items",
                            updateSelector:"#gecg .pager a, #gecg .items thead th a",
                            afterAjaxUpdate:function(){}
                          };
})
</script>
于 2012-11-16T15:21:41.263 回答