Come Aggornare Contenuto Tramite Ajax?

Buona sera,

sto cercando da giorni esempi, guide e tutorial su come modificare/aggiornare il contenuto di una view attraverso ajax ma trovo solo guide incomplete, che danno per scontato molte cose e non adatte a neofiti come me.

Perciò, sapreste consigliarmi una guida o spiegarmi per sommi capi com’è che si aggiorna il contenuto di una view?

Quello che voglio fare io è mostrare il risultato di una query alla pressione di un pulsante. Nient’altro.

Grazie.

partiamo con una cosa semplice, utilizzando alcune funzionalità di Yii:

nella view:




echo CHtml::ajaxLink(

	'Test Ajax',

	array('ajax/textajax'), // Controller ajax / action testajax

	array(

		'update'=>'#ajax_div'

	)

);

?>


<div id="ajax_div"></div>



nel Controller ajax:




public function actionTextAjax() {

	echo time();

	Yii::app()->end();

}



Ciao,

in realtà via AJAX puoi fare di tutto, quindi devi essere più chiaro.

Vuoi aggiornare il contenuto di una div, di una GridView, ecc…?

Quando vuoi far scattare la chiamata AJAX (pulsante, link, dropDown, evento, ecc…) ?

Fammi sapere, nessun problema a mostrarti come fare !

Ciao

Ciao ragazzi,

grazie per la vostra disponibilità.

Quello che voglio fare è, alla pressione di un pulsante, richiamare un action (e questo lo so fare) però aggiornare il contenuto della pagina via ajax. Esattamente, quello che devo fare, è filtrare dei risultati dal DB, perciò la funzione actionNomeFunzione non farà altro che fare una query e restituire un risultato.

@st4nny: nel frattempo guardo il tuo esempio!

@st4nny: il tuo esempio funziona (nel link ho dovuto omettere il controller però) ma non ho capito alcune cose:

  1. perchè va messo Yii::app()->end() ?

  2. perchè in altre guide che ho messo viene usato il renderPartial?

@claudio.ferrari: quando vuoi posta anche i tuoi esempi! :lol:

ok, ad esempio, immagina di ripensare il tabularInput, ovvero:

  • da un autocomplete, via AJAX, selezioni oggetti (ActiveRecord)

  • una volta selezionato quello desiderato, crei un oggetto (ad esempio una riga di bom)

  • se la creazione è andata a buon fine, aggiorni una gridView (magari extended con la possibilità di modificare al volo alcuni campi)

  • riaggiorni la grid con i campi modificati

? ok ?

questa è la view, la prima parte, ovvero il registerScript, serve solo per evidenziare i caratteri trovati nell’autocomplete…




<?php

Yii::app()->clientScript->registerScript('highlightAC','$.ui.autocomplete.prototype._renderItem = function (ul, item) {

            item.label = item.label.replace(new RegExp("(?![^&;]+<img src='http://www.yiiframework.com/forum/public/style_emoticons/default/wink.gif' class='bbc_emoticon' alt=';)' />(?!<[^<>]*)(" + $.ui.autocomplete.escapeRegex(this.term) + ")(?![^<>]*>)(?![^&;]+<img src='http://www.yiiframework.com/forum/public/style_emoticons/default/wink.gif' class='bbc_emoticon' alt=';)' />", "gi"), "<strong>$1</strong>");

            return $("<li></li>")

                    .data("item.autocomplete", item)

                    .append("<a>" + item.label + "</a>")

                    .appendTo(ul);

        };',CClientScript::POS_LOAD);

?>




<div class="control-group ">

            <label class="control-label" for="searchKey"><?php echo Yii::t('labels','Search Key'); ?>: </label>

            <div class="controls">


<?php

        //$items=$model->getBomRows();

        $this->widget('zii.widgets.jui.CJuiAutoComplete', array(

            //'model'=>$model,

            'name'=>'searchKey',

            'id'=>'item_name',

            'source'=>'js: function(request, response) {

                $.ajax({

                    url: "'.$this->createUrl('searchKey/autocomplete').'",

                    dataType: "json",

                    data: {

                        term: request.term,

                        nodeId: '.$model->page_id.',

                    },

                    success: function (data) {

                        response(data);

                    }

                })

            }',

            // additional javascript options for the autocomplete plugin

            'options'=>array(

                'showAnim'=>'fold',

                'select'=>"js:function(event, ui) {

                    addKey(ui.item.datSearchKey.id);

                    $(this).val('');return false;

                }",

            ),

            'htmlOptions'=>array(

                //'disabled'=>$disabled,

                'class'=>'span7'

            ),

        ));

    ?>

            </div>

        </div>

<?php

$datBomDataProvider=new CActiveDataProvider('CmsSearchKeyContent', array(

    'criteria'=>array(

        'with'=>array('searchKey'),

        'condition'=>'content_id=:fatherID',

        'params'=>array(':fatherID'=>$model->id),

        'order'=>'searchKey.name ASC',

     ),

     'pagination'=>array(

        'pageSize'=>200,

     ),

));


$this->widget('bootstrap.widgets.TbExtendedGridView', array(

    'id'=>'dat-content-key-grid',

    //'filter'=>$filterModel,

    'type'=>'striped bordered',

    'dataProvider' => $datBomDataProvider,

    'template' => "{items}",

    'columns' =>array(

        //array('name'=>'id', 'header'=>'#', 'htmlOptions'=>array('style'=>'width: 60px')),

        array('name'=>'key_id', 'value'=>'$data->searchKey!= null ? $data->searchKey->name : \'\'', 'header'=>'ID'),

        array(

            'name'=>'value',

            'header'=>'Value',

			//'headerHtmlOptions' => array('style' => 'width:50px; align:right'),

            'class'=>'bootstrap.widgets.TbJEditableColumn',

            'saveURL' => $this->createUrl('cmsSearchKeyContent/contentKey'),

            'jEditableOptions' => array(

	            'type' => 'text',

				// very important to get the attribute to update on the server!

	            'submitdata' => array('attribute'=>'value'),

	            'cssclass' => 'form',

                //'event'=>'dblclick',

	            'width' => 'auto',//'180px',

                //'class' => 'span12',


            )

        ),

        //if use editableSaver....

        /*

        array(

            'class' => 'bootstrap.widgets.TbEditableColumn',

            'name' => 'quantity',

            'sortable'=>true,

            'editable' => array(

                'url' => $this->createUrl('datItem/editableSaver'),

                'placement' => 'right',

                'inputclass' => 'span3',

                //'onRender'=>'js:alert("OK");'

            )

        ),*/

        array(

            'htmlOptions' => array('nowrap'=>'nowrap'),

            'class'=>'bootstrap.widgets.TbButtonColumn',

            'template'=>'{delete}',

            'deleteButtonUrl'=>null,

        ),

    ),

));

?>

<script>

// Add item record to dat_bom

function addKey(datSearchKeyId){

    alert(datSearchKeyId);


    <?php

    echo CHtml::ajax(array(

        // the controller/function to call

        'url'=>CController::createUrl('searchKeyContent/ajaxAddKey'),

        // Data to be passed to the ajax function

        'data'=>array(

            'content_id'=>$model->id,

            'locale'=>$locale,

            'raw_id'=>'js:datSearchKeyId',

        ),

        'type'=>'post',

        'dataType'=>'json',

        'success'=>"function(data){

            if(data.error=='false'){

                $.fn.yiiGridView.update('dat-content-key-grid');

            }

        } ",

        ))?>;

}

</script>



e queste sono le action dei controller (l’action autocomplete di un altro controller, nell’esempio, il SearchKeyController la trovi sotto…)




    public function actionAjaxAddKey(){

        if (Yii::app()->request->isAjaxRequest)

        {

            $pageId = Yii::app()->request->getParam( 'page_id' );

            $contentId = Yii::app()->request->getParam( 'content_id' );

            $locale = Yii::app()->request->getParam( 'locale' );

            $rawId = Yii::app()->request->getParam( 'raw_id' );

            try{

                $content = CmsPageContent::model()->findByAttributes(array('page_id'=>$pageId,'locale'=>$locale));

                $bom = new CmsSearchKeyContent;

                $bom->content_id=$content->id;

                $bom->search_key_item_id=$rawId;

                $bom->locale=$locale;

                $bom->value='Inserire uno o più valori separati da ","';

                $bom->save(false);


                $status='Everything has gone well';

                $error='false';


                echo CJSON::encode(array(

                    'error' => $error,

                    'status' => $status,

                ));

                Yii::app()->end();


            }catch(Exception $e){

                $status='Exception caugth in ajaxAddKey : '.$e;

                echo CJSON::encode(array(

                    'error' => 'true',

                    'status' => $status,

                ));

                Yii::app()->end();

            }

        }

    }


    public function actionEditableSaver()

    {


        Yii::import('bootstrap.widgets.TbEditableSaver');

        $es = new TbEditableSaver('CmsSearchKeyContent');

        $es->update();

        //echo "<script type='text/javascript'>javascript:$.fn.yiiGridView.update('dat-attachment-grid');</script>";

    }



e questa è la action autocomplete di SearchKeyController:




	public function actionAutocomplete($pageId,$contentId,$language)

    {


        $contentKeys = $this->getContentKeys($contentId);

        $results = array();

        $res =array();

        if (isset($_GET['term'])) {

$qtxt ="SELECT * FROM cms_search_key WHERE ((LOWER(cms_search_key.name) LIKE :name OR LOWER(cms_search_key.description) LIKE :name) AND id NOT IN ".$contentKeys.") ORDER BY cms_search_key.name";

$qtxt = "select * from cms_search_key

left join cms_search_key_item on cms_search_key_item.search_key_id

left join cms_search_key_content on cms_search_key_content.search_key_item_id

WHERE ((LOWER(cms_search_key.name) LIKE :name OR LOWER(cms_search_key.description) LIKE :name)

AND (cms_search_key_item.id NOT IN ".$contentKeys." and cms_search_key_item.locale=\"".$language."\")) ORDER BY cms_search_key.name";


$qtxt="..."; //your sql query (too long to show)




            $command =Yii::app()->db->createCommand($qtxt);

            $command->bindValue(":name", '%'.strtolower($_GET['term']).'%', PDO::PARAM_STR);

            $res =$command->queryAll();


            foreach($res as $datSK)

            {

                $datSearchKeyItem = CmsSearchKeyItem::model()->findByAttributes(array('search_key_id'=>$datSK['id'],'locale'=>$language));

                $results[] = array(

                    'label'=>$datSK['name'].' - '.$datSK['description'],   // viene visualizzato in search

                    'value'=>$datSK['name'],                        // viene visualizzato dopo select .' - '.$p['description'],

                    'id'=>$datSK['id'],

                    'locale'=>$language,

                    'datSearchKeyItem'=>$datSearchKeyItem

                    );

            }


        }

        echo CJSON::encode($results);

        Yii::app()->end();

	}



Riassumendo:

  • hai visto come chiamare action AJAX passando parametri:

  • giocando, in poche righe di codice, con n action in m controller;

  • gestire gli oggetti ritornati dalle action;

Fammi sapere se hai bisogno di chiarimenti; probabilmente i guru AJAX mi manderebbero a quel paese (vero Zaccaria e Sensorario ?), ma, ti assicuro che funziona tutto (anche se tutto è "perfettibile")

Ciao

@tab

  1. perchè va messo Yii::app()->end() ?
  • la chiamata deve terminare per ritornare
  1. perchè in altre guide che ho messo viene usato il renderPartial?
  • il renderPartial viene usato per mandare direttamente una view. Nell’esempio postato da me, una volta cliccato il link avrai il timestamp attuale nel div, con un renderPartial ti troveresti la view desiderata.
    1. dipende da quello che devi fare:

? vuoi ritornare dati al chiamante, vuoi ridirigere il success della chiamata, vuoi fare un render/renderPartiaL, …

come hai visto, puoi fare di tutto…