2013-02-23 156 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,你是男人。