Dato che Twitter Boostrap (v3) è il front-end framework più utlizzato, nonchè quello “installato” di default con la ZendSkeletonApplication vediamo come aggiornare il Navigation Menu Helper affinchè si adatti alla Navbar di Boostrap.
Problema
Il problema principale è che di default il navigation menu helper rende, logicamente, un menù con sintassi neutra:
<ul class="navigation"> <li class="active"> <a href="/products/server">Foo Server</a> </li> <li> <a href="/products/studio">Foo Studio</a> </li> </ul>
E fin qui tutto bene. Tuttavia in caso di sotto menù renderà qualcosa tipo:
<ul class="navigation"> <li class="active"> <a href="/products/server">Foo Server</a> <ul> <li class="active"> <a href="/products/server/faq">FAQ</a> </li> <li> <a href="/products/server/editions">Editions</a> </li> <li> <a href="/products/server/requirements">System Requirements</a> </li> </ul> </li> </ul>
che male si adatta alla Navbar di Boostrap.
Soluzione
Una soluzione sarebbe quella di rendere un menù ad unica profondità:
<?php echo $this->navigation('my_navigation') ->menu() ->setUlClass('nav navbar-nav') ->setMaxDepth(0) ->setRenderInvisible(false)?>
Tuttavia in questo modo non risolviamo il problema ma lo bypassiamo.
La soluzione migliore sarebbe quella si utilizzare i partials per rendere il menù all’interno di un nostro template.
Il nostro partial potrebbe essere qualcosa di simile a questo:
application/navigation/mynav.phtml
<ul class="<?= $this->navigation()->menu()->getUlClass() ?>"> <?php foreach ($this->container as $page): ?> <?php if (!$page->isVisible() || !$this->navigation()->accept($page)) continue; ?> <?php $hasChildren = $page->hasPages() ?> <?php if (!$hasChildren): ?> <li<?php if ($page->isActive()) echo ' class="active"'; ?>> <a href="<?php echo $page->getHref() ?>"> <?php if (null !== $page->get("icon")): ?> <i class="<?php echo $page->get("icon"); ?>"></i> <?php endif; ?> <?= $this->translate($page->getLabel()) ?> </a> </li> <?php else: ?> <li class="dropdown<?php if ($page->isActive()) echo ' active'; ?>"> <a href="#" class="dropdown-toggle" data-toggle="dropdown"> <?php if (null !== $page->get("icon")): ?> <i class="<?php echo $page->get("icon"); ?>"></i> <?php endif; ?> <?= $this->translate($page->getLabel()) ?> <b class="caret"></b> </a> <ul class="dropdown-menu"> <?php foreach ($page->getPages() as $child): ?> <?php if (!$child->isVisible() || !$this->navigation()->accept($child)) continue; ?> <li<?php if ($child->isActive()) echo ' class="active"'; ?>> <a href="<?php echo $child->getHref() ?>"> <?php if (null !== $child->get("icon")): ?> <i class="<?php echo $child->get("icon"); ?>"></i> <?php endif; ?> <?= $this->translate($child->getLabel()) ?> </a> </li> <?php endforeach ?> </ul> </li> <?php endif ?> <?php endforeach ?> </ul>
A questo punto possiamo usare la Navigation factory di default (\Zend\Navigation\Service\DefaultNavigationFactory
) oppure crearcene una propria:
namespace Application\Navigation\Service; use Zend\Navigation\Service\DefaultNavigationFactory; class MyNavigationFactory extends DefaultNavigationFactory { protected function getName() { return 'mynav'; } }
Quindi in un config file:
return array( 'service_manager' => array( 'factories' => array( 'my_navigation' => 'Application\Navigation\Service\MyNavigationFactory', ), ), );
Nella layout view:
<?php echo $this->navigation('my_navigation') ->menu() ->setUlClass('nav navbar-nav') ->setMaxDepth(1) ->setPartial(array('partial/mynav.phtml', 'Application')) ?>
Esempio utlizzo:
'navigation' => array( 'admin' => array( 'mynav' => array( 'label' => 'Home', 'route' => 'home', 'order' => -1, 'icon' => 'glyphicon glyphicon-home', 'pages' => array( array( 'label' => 'Page1', 'route' => 'application/page1', ), array( 'label' => 'Page2', 'uri' => '/application/page2', ), array( 'label' => 'Page3', 'route' => '/application/page3', ), ), ), ), ),
Conclusioni
Da tenere presente che così com’è scritto il partial tiene in considerazione un solo livello di profondità.
Inoltre al fine di supportare il caret in caso di menù con sottolivelli e le icone sulle voci del menù l’helper è venuto piuttosto “laborioso”.
Se avessimo rinunciato a questi avremmo potuto utilizzare il metodo htmlify()
del Zend\View\Helper\Navigation\Menu
che avrebbe reso il codice un po’ più snello.
Il metodo ritorna una stringa contenente un elemento ‘a’ per la pagina data se l’href non è vuoto, ed un elemento ‘span’ se questo è vuoto.
<?php echo $this->navigation()->menu()->htmlify($page) . PHP_EOL; ?>
Github
https://github.com/simogrima/Zf2-TwitterBoostrap-NavigationMenu
Risorse
http://framework.zend.com/manual/2.1/en/modules/zend.navigation.view.helper.menu.html
http://stackoverflow.com/questions/14884572/zend-framework-2-navigation-menu-twitter-bootstrap-integration
2 risposte su “ZF2 Navigation Menu con integrazione di Twitter Bootstrap”
Sei un grande Simogrima…
grandissimo, ottimo articolo