Albero ajax

Ho avuto il problema di creare un albero prendendo categorie e subcategorie dal database; il tutto con una certa user experience, per cui possibilmente ajax. Avevo provato il plugin sfgWidgetsPlugin ma non permette più di un innesto (manca qualcosa tipo evalScript: true nella chiamata ajax), per cui ho dovuto fare a mano.

A seguito la mia soluzione.

Prima di tutto nella mia action tiro fuori la prima serie di categorie:

1
2
3
4
5
6
7
8
 
private function getCategorie()
{
  $c = new Criteria();
  $c->addAscendingOrderByColumn(CategoriePeer::CATEGORIE);
  $this->categorie = CategoriePeer::doSelect($c);
  $this->forward404Unless($this->categorie);
}

Dopodiché, nel template, ciclo sulle tuple trovate:

1
2
3
4
 
<?php foreach ($categorie as $categoria): ?>
<p class="categoria">
<p class="catname_div">

Voglio mettere l’iconcina con il classico “+” nel caso ci sia almeno una sottocategoria, per cui:

1
2
<?php $c = new Criteria(); $c->add(SottocategoriePeer::RIF_CATEGORIE, $categoria->getIdCategorie(), Criteria::EQUAL); $sottocat_count = SottocategoriePeer::doCount($c); ?>
<?php if ($sottocat_count > 0) echo image_tag('explode.gif', array('id' => 'img_'.$categoria->getIdCategorie())); ?>

Ora ci occorrerebbe il famoso helper link_to_remote per poter accedere alle sub-sub-categorie; però mi piacerebbe poter clikkare sul nome di una categoria sia per espandere l’albero che per chiuderlo. Per questo motivo la chiamata ajax deve essere condizionale con un ramo else, cosa non permessa dall’helper, per cui vado a mano:

1
2
<a href="#" onclick="if (document.getElementById('sottocat_<?php echo $categoria->getIdCategorie() ?>').innerHTML == '') {new Ajax.Updater('sottocat_<?php echo $categoria->getIdCategorie() ?>', 'categorie/trovasotto/id/<?php echo $categoria->getIdCategorie() ?>', {asynchronous:true, evalScripts:true, onComplete:function(request, json){document.getElementById('img_<?php echo $categoria->getIdCategorie() ?>').src='/images/implode.gif'; Element.hide('indicator');}, onLoading:function(request, json){Element.show('indicator')}}); return false;} else {document.getElementById('sottocat_<?php echo $categoria->getIdCategorie() ?>').innerHTML = ''; document.getElementById('img_<?php echo $categoria->getIdCategorie() ?>').src='/images/explode.gif'}">
<?php echo $categoria->getCategorie() ?></a>

Non faccio altro che dire “se il div che riempio tramite la chiamata remota ha del contenuto (leggi: è espanso) allora setta il suo contenuto a vuoto e metti come iconcina di nuovo il “+” (leggi: chiudilo), altrimenti fai la chiamata remota e l’iconcina diventa un “-” (leggi: espandilo).

Infine la chiamata remota per poter aggiungere nuove sottocategorie ed i div necessari:

1
2
3
4
5
6
7
8
9
10
<div id="addsottocateg_div"><?php echo link_to_remote('+', array(
  'url' => 'categorie/aggiungiSotto?id='.$categoria->getIdCategorie(),
  'update' => 'acs_'.$categoria->getIdCategorie(),
  'script' => true,
)) ?>
</div>
<div class="acs" id="acs_<?php echo $categoria->getIdCategorie() ?>"></div>
<div class="sottocategoria_div" id="sottocat_<?php echo $categoria->getIdCategorie() ?>"></div>
</div>
<?php endforeach; ?>

Tutto questo non sarebbe stato necessario se il mitico sfgWidgetsPlugin avesse una opzione “scripts => true” per permettere l’evaluate di script anche nella destinazione.

One Reply to “Albero ajax”

Leave a Reply

Your email address will not be published. Required fields are marked *