2013-02-23 153 views
9

如何將自定義屬性添加到Zend Framework 2導航中?
我知道我可以添加id或class - >但僅此而已....導航中的ZF2自定義屬性

1)我將如何添加data-test='blahblah'屬性例如?
2)我可以將屬性添加到包含實際鏈接的li元素嗎?

$container = new Zend\Navigation\Navigation(array(
    array(
     'label' => 'Page 1', 
     'id' => 'home-link', 
     'uri' => '/', 
    ), 
    array(
     'label' => 'Zend', 
     'uri' => 'http://www.zend-project.com/', 
     'order' => 100, 
    ), 
); 

編輯:

@Bram Gerritsen的:謝謝您的回答。

是 - 我可以添加'data-test' => 'blahblah'和檢索它作爲$page->get('data-test') - 但這仍然不能將其追加爲屬性爲<a></a> ....我會ahve覆蓋htmlify對嗎?

回答

10

的頁面類別有共同的屬性(setLabelsetIdsetUri等)的一些專用的制定者,如果不制定者存在__set將被調用。請參閱manual瞭解關於此的更多信息,以及關於擴展AbstractPage類的更多信息。

array(
    'label' => 'Page 1', 
    'id' => 'home-link', 
    'uri' => '/', 
    'data-test' => 'blahblah' 
), 

現在你可以做$page->get('data_test')它會返回blahblah。

你的第二個問題是關於改變菜單的渲染(增加了li一個屬性。ZF2是使用menu view helper來呈現導航菜單。 所有導航視圖助手必須使用自己的局部視圖選項使用setPartial()渲染

在你viewscript:

$partial = array('menu.phtml', 'default'); 
$this->navigation()->menu()->setPartial($partial); 
echo $this->navigation()->menu()->render(); 

在您的局部視圖menu.phtml做這樣的事情:

<ul> 
<?php foreach ($this->container as $page): ?> 
    <li data-test="<?=$page->get('data_test')?>"><?=$this->navigation()->menu()->htmlify($page)?></li> 
<?php endforeach; ?> 
<ul> 

這將只呈現菜單的最高級別。如果你有更深的/嵌套的結構,你的自定義視圖腳本將變得更加複雜。

希望這會有所幫助。

+0

謝謝您的回答。 是 - 我可以添加「數據測試」 =>「blahblah」和檢索它作爲$頁面級>的get(「數據測試」) - 但仍無法將其追加爲屬性爲 .. ..我必須重寫htmlify到那個? – 2013-02-24 00:56:20

+0

是的,你需要擴展菜單視圖助手,並且只能覆蓋htmlify方法。看看htmlify方法,你會看到數組定義的attrib。你可以在那裏添加你的自定義屬性。看到我的【答案】(http://stackoverflow.com/questions/15017288/injecting-custom-navigation-using-a-view-helper-through-the-servicemanager/15019924#15019924)上的另一SO如何註冊質疑您自己的導航視圖助手。 – 2013-02-24 01:31:35

+0

感謝您的回覆。所以 - 我的菜單實際上有2個層次的深度...所以基本上 - 視圖部分 - 我必須遞歸迭代容器 - 正確嗎?我不能只是簡單地對頁面項目進行foreach ... – 2013-02-24 04:01:21

25

布拉姆的回答幫助指向我一個解決方案,這就是我需要的,我怎麼解決的,(因爲我是新來ZF2和命名空間,我花了比它應該有更長的時間,所以希望這將幫助其他人)

問題

  • 想用Zend\Navigation從其isActive()方法,有利於建於翻譯,ACL等支持。
  • 需要將CSS類名稱添加到<li>元素<a>元素。 (ZF2的菜單視圖助手目前支持'或'方法)
  • 需要將CSS類名添加到嵌套的<ul>元素。
  • 需要這樣的data-*="..."
  • 需要這些更改,以支持引導3標記的附加屬性添加到<a>元素

解決方案描述

  • 通過創建客戶視圖助手延伸Zend\View\Helper\Navigation\Menu
  • 稍微修改renderNormalMenu()htmlify()方法的自定義屬性添加到Zend\Pages到CSS類和額外的屬性添加到某些元素的能力

解決方案

  • 利用

    步驟1

    Creat在\module\Application\Module.php

    <?php 
    /** 
    * Zend Framework (http://framework.zend.com/) ...*/ 
    
    namespace Application; 
    
    use Zend\Mvc\ModuleRouteListener; 
    use Zend\Mvc\MvcEvent; 
    
    class Module 
    { 
        // ** snip ** 
    
        public function getViewHelperConfig() { 
         return array(
          'invokables' => array(
           // The 'key' is what is used to call the view helper 
           'NewMenu' => 'Application\View\Helper\NewMenu', 
          ) 
         ); 
        } 
    } 
    

    步驟3版自定義視圖助手應用程序模塊src\Application\View\Helper\NewMenu.php

    NewMenu.php

    <?php 
    namespace Application\View\Helper; 
    
    // I'm extending this class, need to include it 
    use Zend\View\Helper\Navigation\Menu; 
    
    // Include namespaces we're using (from Zend\View\Helper\Navigation\Menu) 
    use RecursiveIteratorIterator; 
    use Zend\Navigation\AbstractContainer; 
    use Zend\Navigation\Page\AbstractPage; 
    
    
    class NewMenu extends Menu 
    { 
        // copied fromZend\View\Helper\Navigation\Menu 
        protected function renderNormalMenu(...){} 
    
        // copied from Zend\View\Helper\Navigation\Menu 
        public function htmlify(...){} 
    } 
    

    步驟2

    註冊新視圖助手下與getViewHelperConfig()

    在我的layout.phtml腳本中,我得到我的導航容器並將它傳遞給NewMenu視圖助手。我還設置了一些選項,例如添加父級<ul>類名稱而不是轉義標籤,以便我可以將Bootstrap使用的標準'dropdown caret'(即<b class="caret"></b>)添加到帶有下拉菜單的標籤。

    $container = $this->navigation('navigation')->getContainer(); 
    echo $this->NewMenu($container)->setUlClass('nav navbar-nav')->escapeLabels(false); 
    

    中場

    在這一點上,我們應該有更多或更少的只是複製了菜單視圖助手。它應該像標準的View Helper一樣產生一個導航。


    步驟4

    NewMenu.php類,我刪除$addClassToListItem代碼,以避免它從由事故放置類錯誤的元件上。

    protected function renderNormalMenu(...)

    // Add CSS class from page to <li> 
    //if ($addClassToListItem && $page->getClass()) { 
    // $liClasses[] = $page->getClass(); 
    //} 
    

    公共職能htmlify(...)

    // Always apply page class to <a> tag. We'll use a diff. method for <li> 
    //if ($addClassToListItem === false) { 
        $attribs['class'] = $page->getClass(); 
    //} 
    

    步驟5

    添加一個方法來CSS類名適用於<li>標籤,因爲我們去掉了$addClassTolistItem方法。我們只需使用Page類的能力,具有自定義屬性,並做到這一點:

    保護功能renderNormalMenu現在

    // Is page active? 
    if ($isActive) { 
        $liClasses[] = 'active'; 
    } 
    
    if($wrapClass = $page->get('wrapClass')){ 
        $liClasses[] = $wrapClass; 
    } 
    ... 
    

    ,在我們的導航配置文件,我們只需添加一個名爲wrapClass應用CSS屬性類包裝元素(<li>)。

    設置\自動加載\ global.php

    ... 
    'navigation' => array(
        'default' => array(
         ... 
         array(
          'label' => 'Products <b class="caret"></b>', 
          'route' => 'products', 
          'wrapClass' => 'dropdown',   // class to <li> 
          'class'  => 'dropdown-toggle', // class to <a> like usual 
          'pages' => array(
           array(
            'label' => 'Cars', 
            'route' => 'products/type', 
            ... 
           ), 
           ... 
          ), 
         ), 
    ... 
    

    步驟6

    添加到對<a>附加屬性等data-*的能力。對於Bootstrap 3,例如,您需要data-toggle="dropdown"

    公共職能htmlify(...)

    // get attribs for element 
    $attribs = array(
        'id'  => $page->getId(), 
        'title' => $title, 
    ); 
    
    // add additional attributes 
    $attr = $page->get('attribs'); 
    if(is_array($attr)){ 
        $attribs = $attribs + $attr; 
    } 
    

    在您的配置文件,你現在可以添加一個屬性與附加屬性的數組:

    配置\自動加載\全球。 PHP

    ... 
    'navigation' => array(
        'default' => array(
         ... 
         array(
          'label' => 'Products <b class="caret"></b>', 
          'route' => 'products', 
          'wrapClass' => 'dropdown',   // class to <li> 
          'class'  => 'dropdown-toggle', // class to <a> like usual 
    
          'attribs' => array(
           'data-toggle' => 'dropdown', // Key = Attr name, Value = Attr Value 
          ), 
    
          'pages' => array(
           array(
            'label' => 'Cars', 
            'route' => 'products/type', 
            ... 
           ), 
           ... 
          ), 
         ), 
    ... 
    

    步驟7

    添加在嵌套列表容器上放置類名的功能(例如, <ul>)。

    保護功能renderNormalMenu()

    if ($depth > $prevDepth) { 
        // start new ul tag 
        if ($ulClass && $depth == 0) { 
         $ulClass = ' class="' . $ulClass . '"'; 
        } 
    
        // Added ElseIf below 
    
        else if($ulClass = $page->get('pagesContainerClass')){ 
         $ulClass = ' class="' . $ulClass . '"'; 
        } 
    
        else { 
         $ulClass = ''; 
        } 
        $html .= $myIndent . '<ul' . $ulClass . '>' . self::EOL; 
    

    原來的代碼基本上說:「如果這是第一次<ul>,有一個UL類,添加它,別的什麼也不做。所以,我增加了一個額外的檢查。就是說,如果一個屬性叫pagesContainerClass是可用的,對類適用於<ul>以及

    這意味着我們需要在我們的配置中添加右側頁面的屬性:

    config \ autoload \ global。PHP

    ... 
    'navigation' => array(
        'default' => array(
         ... 
         array(
          'label' => 'Products <b class="caret"></b>', 
          'route' => 'products', 
          'wrapClass' => 'dropdown',   // class to <li> 
          'class'  => 'dropdown-toggle', // class to <a> like usual 
    
          'attribs' => array(
           'data-toggle' => 'dropdown', // Key = Attr name, Value = Attr Value 
          ), 
    
          'pages' => array(
           array(
            'label' => 'Cars', 
            'route' => 'products/type', 
            // Give child <ul> a class name 
            'pagesContainerClass' => 'dropdown-menu', 
            ... 
           ), 
           ... 
          ), 
         ), 
    ... 
    

    重要的是注意,UL類需要放在一個孩子的第一個子頁面是因爲條件語句被包裹在以下條件:

    if ($depth > $prevDepth) { 
        // start new ul tag 
        ... 
    } 
    

    第一後孩子被調用,$ dept = $ prevDepth和嵌套的<ul>已經被髮送到字符串緩衝區。


    該解決方案還沒有被嚴格的測試,但這個想法是簡單地取當前菜單視圖助手,和過載的兩個必要方法和僅略微修改了。

    我試着使用setPartial(),但只有具有<li>代的幫助下,該公司仍使用菜單視圖助手htmlify()方法(所有這些都在布拉姆的討論上面提到的)。

    因此,與使這些小tweeks的方法和使用Page類的具有自定義屬性的能力,我可以添加一些額外的邏輯來獲得關於<li><a>和嵌套<ul>類的類名,以及添加額外的屬性的<a>元素,所以我可以配置我的Zend\Navigation從配置吐出來,基本上,Bootstrap 3 Navbar標記。

    最終佈局則看起來就像這樣:

    <nav class="navbar navbar-default navbar-static-top" role="navigation"> 
        <div class="navbar-header"> 
         <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse"> 
          <span class="sr-only">Toggle navigation</span> 
          <span class="icon-bar"></span> 
          <span class="icon-bar"></span> 
          <span class="icon-bar"></span> 
         </button> 
        </div> 
        <div class="collapse navbar-collapse navbar-ex1-collapse"> 
        <?php 
         // Use Zend\Navigation to create the menu 
         $container = $this->navigation('navigation')->getContainer(); 
         echo $this->NewMenu($container)->setUlClass('nav navbar-nav')->escapeLabels(false); 
        ?> 
        </div><!-- /.navbar-collapse --> 
    </nav> 
    

    我一直運行到的煩惱是更好地瞭解PHP命名空間,並具有需要包括相應的合格的命名空間在我的自定義視圖助手,即使我正在擴展它。

    的另一個問題,是導航視圖助手可以調用菜單視圖助手從本身就像這樣:

    $this->navigation('navigation')->menu(); 
    

    這是行不通的:

    $this->navigation('navigation')->NewMenu(); 
    

    我想是因爲與NewMenu沒有在Navigation View Helper類中註冊的命名空間問題,我不打算僅僅爲此而擴展它。

    所以,希望這(長)答案將有助於其他誰正在努力滿足這種需求。

    乾杯!

  • +0

    TOP !!簡直太神奇了,不能更清晰,像魅力一樣工作...... – cwhisperer 2014-06-30 11:18:27

    1

    除了jmbertucci評論

    問題在標籤

    exсess插入符標籤,該標籤會導致問題:

    • 麪包
    • 菜單翻譯

    Splution

    要防止添加標籤插入標籤標籤您可以在菜單配置添加此參數的支持。你應該

    轉到

    src\Application\View\Helper\NewMenu.php 
    

    保護功能renderNormalMenu()

    /// add 4th parameter $page->get('caret') 
    $html .= $myIndent . ' <li' . $liClass . '>' . PHP_EOL . 
    $myIndent . '  ' . 
    $this->htmlify($page, $escapeLabels, $addClassToListItem, $page->get('caret')) . PHP_EOL; 
    

    公共職能htmlify()

    } else { 
        $html .= $label; 
    } 
    //// add this if 
    if($caret === true){ 
        $html .= '<b class="caret"></b>'; 
    } 
    
    $html .= '</' . $element . '>'; 
    

    現在你可以使用它:

    array(
           'label' => 'Some label', 
           'caret' => true, 
           'route' => 'someroute', 
           'wrapClass' => 'dropdown', 
           'class' => 'dropdown-toggle', 
    

    ps。 jmbertucci,你是男人。