jqueryajaxtwitter-bootstrapyiizii-widgets

Yii & Bootstrap widgets not working after second Ajax


To improve initial page loads most of the content on the page I'm creating are loaded only when required. To do this I'm using the following code via an ajax call.

$this->renderPartial('_callhistory', array(
                        'modelCalls'=>$modelCalls,
                        'fid'=>$fid,                        
), false, true);

This works fine, all of the widgets work. It's causing issues with the main theme's design, but thats not a major issue at the moment.

The problem I'm having is on occasion the ajax needs to be called again to update the view. to do this I'm calling the exact same ajax function with the same parameters, but on the second call all the widgets (namely: TbSelect2 and CJuiDatePicker) stop working, instead I get the standard select and a textbox for the date. This in turn breaks the client-side validation.

Other Q&As mention .unbind(), is this the way to go? If so, am I right in saying all widget elements need to unbind before the ajax call?

Thanks, I'll post my Ajax too, just note it handles all updates like this one.

function renderSectionView(fid, viewid, headerid, panelid, extraparams){
    var panel = $('#'+panelid);
    panel.html("<img src='images/ajax-loader-bar.gif' class='loadingbar' />");

    var param = {   'fid':fid,
            'viewid':viewid
            };  

    var url = controller_url_builder('SubViewAjax', param);

    var jqxhr = $.post( url, extraparams, function(data) {
        panel.html(data);
    })
    .done(function() {
        renderedlist.push(viewid+fid);
    })
    .fail(function() {
        panel.html("<span class='error'>There has been an error, please refresh the page and try again</span>");
    })
    .always(function() {
        scrollToAcc(headerid);
    });
}

Solution

  • I have finally found an answer to this thanks to here:

    Yii Framework Forum: ajax and widgets

    The trick is to render the widget in your controller, but store the output as a variable like so:

    $html = $this->widget( $className,  $properties=array ( ), TRUE);
    

    NOTE: The final 'true' parameter allows you to place the result in the $html variable.

    Then render your scripts with the help of the client script.

    Yii::app()->getClientScript()->renderBodyBegin($html);
    Yii::app()->getClientScript()->renderBodyEnd($html);
    

    Then just pass the variable to the view (I'm doing it via renderPartial) and use echo $html where you need the widget