Categorie
PHP

ZF2 Navigation Menu con integrazione di Twitter Bootstrap

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”

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.