如何在Zend Framework 2导航中添加自定义属性?
我知道我可以添加id或class - >但那是关于它......
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>
....我是否应该覆盖htmlify到那个?
答案 0 :(得分:25)
<强>问题强>
Zend\Navigation
从其isActive()
方法和内置翻译,ACL等支持中受益。<li>
元素和 <a>
元素。 (ZF2&#39;菜单视图助手目前支持“或”或“&#39;”<ul>
元素。<a>
元素添加其他属性,例如data-*="..."
解决方案说明
Zend\View\Helper\Navigation\Menu
renderNormalMenu()
和htmlify()
方法Zend\Pages
添加自定义属性的功能,为某些元素添加CSS类和其他属性<强>解决方案强>
第1步
在应用程序模块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()
\module\Application\Module.php
注册了新的View帮助程序
<?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步
在我的layout.phtml
脚本中,我获取了Navigation容器并将其传递给NewMenu视图助手。我还设置了一些选项,例如添加父<ul>
类名称而不是转义标签,以便我可以添加标准&#39;下拉插件&#39; Bootstrap使用(即<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
代码,以避免它意外地将类放在错误的元素上。
受保护的函数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 classes功能来拥有自定义属性并执行此操作:
受保护的函数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;
}
在配置文件中,您现在可以添加一个包含其他属性数组的属性:
设置\自动加载\ 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',
...
),
...
),
),
...
第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;
原始代码基本上说&#34;如果这是第一个<ul>
并且有UL类,请添加它,否则什么也不做。所以,我添加了一个额外的检查,如果有一个名为pagesContainerClass
的属性可用,也可以将该类应用到<ul>
。
这意味着我们需要在配置中的右页面上添加属性:
设置\自动加载\ 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>
代产生了帮助,它仍然使用菜单视图助手&#39; htmlify()
方法(所有这些都在Bram上面的讨论中提到过。)
因此,通过将这些小小的tweek用于to方法并使用Page类具有自定义属性的能力,我可以添加一些额外的逻辑来获取<li>
上的类名,{{1 }和嵌套的<a>
类以及在<ul>
元素上添加其他属性,因此我可以从配置中配置我的<a>
以吐出,基本上是Bootstrap 3 Navbar标记。 / p>
结束布局然后看起来像这样:
Zend\Navigation
我遇到的麻烦是更好地理解PHP命名空间,并且需要在我的自定义View Helper中包含适当的Qualified名称空间,即使我正在扩展它。
另一个问题是导航视图助手可以像这样调用菜单视图助手:
<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>
这不会起作用:
$this->navigation('navigation')->menu();
我正在考虑因$this->navigation('navigation')->NewMenu();
没有在导航视图助手类中注册的名称空间问题,而且我不会仅为此扩展它。
所以,希望这个(长期)答案可以帮助那些正在努力满足这种需求的人。
干杯!
答案 1 :(得分:10)
Page类有一些专用的公共属性设置器(setLabel
,setId
,setUri
等),如果不存在setter __set
将被调用。有关此问题以及有关扩展AbstractPage
类的详细信息,请参阅manual。
array(
'label' => 'Page 1',
'id' => 'home-link',
'uri' => '/',
'data-test' => 'blahblah'
),
现在你可以做$page->get('data_test')
它将返回blahblah。
您的第二个问题是改变菜单的呈现(向li
添加属性.ZF2正在使用menu view helper呈现导航菜单。
所有导航视图助手都可以选择使用您自己的局部视图进行渲染,使用setPartial()
。
在你的意见稿中:
$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>
这只会呈现菜单的最高级别。如果您有更深层/嵌套的结构,您的自定义视图脚本将会变得更加复杂。
希望这有帮助。
答案 2 :(得分:1)
除了 jmbertucci 评论
ex.gess标签中的插入标签导致问题:
要防止将标签插入符号添加到标签,您可以在菜单配置中添加对此参数的支持。你应该
转到
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 ,你是男人。