Strange behaviour of CHtml::ajaxLink within paging in CListView.

Hi folks,

I found quite strange behaviour of ClistView. I think it would be best if I’ll show you code which I have and will describe problem at the bottom.

in controller ArtistsController.php I have this code:




	public function actionIndex()

	{

 

		$dataProvider=new CActiveDataProvider('artists', array(

                'pagination'=>array(

                    'pageSize'=>32,

                ),

                'sort'=>false,

                ));


                $this->render('index',array(

			'dataProvider'=>$dataProvider,

		));

                 

	}



In index view I have this code:




<?php $this->widget('zii.widgets.CListView', array(

	'dataProvider'=>$dataProvider,

	'itemView'=>'_view',

        'template'=>'{sorter}<br />{pager}{items}<br />{pager}', //{summary}

        'enableSorting' => false,

        'sortableAttributes'=>array(

            'name'=>'by name',

        ),

        'pager'=>array(

          'class'=>'CLinkPager',

          'cssFile'=>$pager_css_location,

          'prevPageLabel'=>'<',

          'nextPageLabel'=>'>',

        ),

)); ?>



And in _view.php(item for DataProvider) I have the following AjaxLinks:




        $ajax_follow_artist_list = $this->beginWidget('CActiveForm', array(

            'id'=>'ajaxfollowartistlist-form',

            'enableAjaxValidation'=>false,

            'action'=>$followed_artists_form_url,

        ));


        echo CHtml::ajaxLink("Follow",Yii::app()->createUrl('artists/ajaxfollowartistfromlist'),

                    array( // ajaxOptions

                        'type' =>'POST',

                        'success'=>"function(data){

                            if(data==\"show_dont_track_button\"){

                                $(\"#dont_track_button$data->id\").show();

                                $(\"#track_button$data->id\").hide();

                            }

                        }",

                        'data' => array('artist_id'=>$data->id)

                    ),

                    array( //htmlOptions

                        'class' => "button small blue",

                        'id' => 'track_button'.$data->id,

                        'style'=>$button_style_track_artist,

                    )

        );


        echo CHtml::ajaxLink("Not follow",Yii::app()->createUrl('artists/ajaxfollowartistfromlist'),

                    array( // ajaxOptions

                        'type' =>'POST',

                        'success'=>"function(data){

                     if(data==\"show_track_button\"){

                        $(\"#dont_track_button$data->id\").hide();

                        $(\"#track_button$data->id\").show();

                     }

                }",

                        'data' => array('artist_id'=>$data->id)

                    ),

                    array( //htmlOptions

                        'class' => "button small red",

                        'id' => 'dont_track_button'.$data->id,

                        'style'=>$button_style_dont_track_artist,

                    )

        );


        $this->endWidget();



So the problem. I can see that Yii only publishes Jquery code for first page of elements (34 elements in my case) the rest is not there and when I click on other page jquery code for next 34 elements is not published on the page. So Ajax functionality is not working obviously, has anyone seen this bug before? I am using Yii yii-1.1.5.r2654.

I can see only this Jquery code for first 34 elements(I use Firebug):




jQuery('body').delegate('#track_button1','click',function(){jQuery.ajax({'type':'POST','success':function(data){

if(data=="show_dont_track_button"){

$("#dont_track_button1").show();

$("#track_button1").hide();

}

},'data':{'artist_id':'1'},'url':'/test2/index.php/artists/ajaxfollowartistfromlist','cache':false});return false;});

jQuery('body').delegate('#dont_track_button1','click',function(){jQuery.ajax({'type':'POST','success':function(data){

if(data=="show_track_button"){

$("#dont_track_button1").hide();

$("#track_button1").show();

}

},'data':{'artist_id':'1'},'url':'/test2/index.php/artists/ajaxfollowartistfromlist','cache':false});return false;});

jQuery('body').delegate('#track_button2','click',function(){jQuery.ajax({'type':'POST','success':function(data){

if(data=="show_dont_track_button"){

$("#dont_track_button2").show();

$("#track_button2").hide();



Just upgraded to version 1.1.8 - same result. Please help.

Hey folks, can anyone from development team look into this issue, I can see that it still happening and it still looks like a bug in the framework.

This is reported already here - http://code.google.com/p/yii/issues/detail?id=2425

Problem is that the "next page" JS code is rendered in the AJAXed page… not on the current page… so that code is never executed… and I dont know if this can be solved at all

in any case IMO it’s a wrong way of doing things to have 34 functions for 34 “same” elements… so the best solution would be to use normal link (non ajax)… and write a custom jQuery function that would bind to all those elements… something like the delete button in CGridView…

This way you would have only one JS funtion for all current and future elements on the page…

Can you please be more specific on this last paragraph with a code snippet if possible. Thanks for a quick reply.

The code for the delete button in CGridView ?




jQuery('#document-grid a.delete').live('click',function() {

	if(!confirm('Are you sure you want to delete this item?')) return false;

	var th=this;

	var afterDelete=function(){};

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

		type:'POST',

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

		success:function(data) {

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

			afterDelete(th,true,data);

		},

		error:function(XHR) {

			return afterDelete(th,false,XHR);

		}

	});

	return false;

});



This code binds the click event to all links with a class “delete” and reads the clicked link href ( $(this).attr(‘href’) ) to get the desired url…

[size=2]Hi thanks for your help, I was on a train that day and my 3G Internet was not very stable so I couldn’t find exact code quicker than you did, thanks, your workaround worked perfectly for me, here is what I did in case anyone will run into the same problem:[/size]

I actually have two buttons and need to track which one was presssed,here is one of them:


 echo CHtml::link($button_iamgoing_text,Yii::app()->createUrl('concerts/ajaxiamgoing',array('going'=>1,'concert_id'=>$data->id)),array('class'=>"button small blue iamgoing$data->id",'id'=>'iamgoing','style' => $button_iamgoing_style));



And here is JQuery code which does an ajax request and using json to get data which I need.




    $('#iamgoing').live('click',function() {

        $.ajax({

            dataType: "json",

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

            success: function(data)

                        {

                            if( data[0].Going == 'show_iamnotgoing_button' ){

                                var text = '  Я иду на этот концерт!';

                                $('#iamgoingtoconcert' + data[0].Id).text(text);

                                $('#iamgoingtoconcert' + data[0].Id).show();

                                $('.imightgo' + data[0].Id).hide();

                                var value = '  Я передумал идти';

                                //$('#iamgoing').text(value);

                                $('.iamgoing' + data[0].Id ).text(value);

                                //Opening popup window

                                $('#popupShareWithFriends' + data[0].Id).bPopup({fadeSpeed:'slow', modalColor:'black', scrollBar:false});

                            }

                            if( data[0].Going == 'show_iamgoing_button' ){

                                $('#iamgoingtoconcert' + data[0].Id).hide();

                                $('.imightgo' + data[0].Id).show();

                                var value = 'Пойду';

                                $('.iamgoing' + data[0].Id).text(value);

                            }

                        }

            });

        return false;

    });



So thanks again, for your help, much appreciated. I LOVE YII!