【问题标题】:Yii "results per page" ajax dropdown breaks after loading other ajax stuff in same pageYii“每页结果”在同一页面中加载其他 ajax 内容后,ajax 下拉菜单中断
【发布时间】:2012-11-14 21:08:55
【问题描述】:

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

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

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

TypeError:设置未定义

内置的 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,
));
?>

想法?

【问题讨论】:

    标签: javascript jquery gridview yii


    【解决方案1】:

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

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

    Yii 将处理程序附加到页面上始终存在(并且必须存在以允许触发事件)的 document 元素。你可以在CGridViewinit方法中看到它作为一个例子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;
        });
    }
    

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

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

    【讨论】:

    • 我确信寻呼机可以在所有加载 ajax 的网格中工作,即使在重新加载其他网格之后也是如此。我正在尝试在每个网格加载后将网格设置设为全局或附加到文档。虽然仍然不确定最好的方法。谢谢。
    【解决方案2】:

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

    这不是一个非常优雅的解决方案(特别是因为寻呼机工作正常,它会导致多个 $.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 视图的末尾,这会将 settings 保存在 window

    <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>
    

    【讨论】:

    • 附带说明一下,我后来不得不修改 CGridView 框架代码,以免因多次重新加载该小部件而创建重复事件。不是最佳的,但它不是为通过 ajax 内联加载而设计的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多