如何在Zend Framework 2导航中添加自定义属性?
我知道我可以添加id或类 - >但这就是它....
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,
),
);
Run Code Online (Sandbox Code Playgroud)
编辑:
@Bram Gerritsen:谢谢你的回答.
是的 - 我可以添加'data-test' => 'blahblah'和检索它$page->get('data-test') - 但是这仍然不会将其作为属性附加到<a></a>....我是否应该将htmlify覆盖到那个?
jmb*_*cci 25
Bram的回答帮助我找到了解决方案,这就是我需要的以及我如何解决它(因为我是ZF2和命名空间的新手,它花了我的时间比它应该有的长,所以希望这会有助于其他人)
问题
Zend\Navigation它的isActive()方法和内置的翻译,ACL等支持.<li>元素和 <a>元素中.(ZF2的菜单视图助手目前支持'或'或'方法)<ul>元素.<a>元素添加其他属性,例如data-*="..."解决方案描述
Zend\View\Helper\Navigation\MenurenderNormalMenu()和htmlify()方法Zend\Pages可以将CSS类和其他属性添加到某些元素中解
步骤1
在Application模块下创建自定义View Helper 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(...){}
}
Run Code Online (Sandbox Code Playgroud)
第2步
注册新的View Helper with getViewHelperConfig()in\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',
)
);
}
}
Run Code Online (Sandbox Code Playgroud)
第3步
在我的layout.phtml脚本中,我获取了我的导航容器并将其传递给NewMenu视图助手.我还设置了一些选项,比如添加父<ul>类名称而不是转义标签,这样我就可以将Bootstrap使用的标准"下拉插入符号"(即.<b class="caret"></b>)添加到带有下拉菜单的标签中.
$container = $this->navigation('navigation')->getContainer();
echo $this->NewMenu($container)->setUlClass('nav navbar-nav')->escapeLabels(false);
Run Code Online (Sandbox Code Playgroud)
幕间休息
此时,我们应该或多或少地重复菜单视图助手.它应该以与标准View Helper相同的方式生成导航.
第4步
在NewMenu.php类中,我删除$addClassToListItem代码以避免它意外地将类放在错误的元素上.
受保护的函数renderNormalMenu(...)
// Add CSS class from page to <li>
//if ($addClassToListItem && $page->getClass()) {
// $liClasses[] = $page->getClass();
//}
Run Code Online (Sandbox Code Playgroud)
公共功能htmlify(...)
// Always apply page class to <a> tag. We'll use a diff. method for <li>
//if ($addClassToListItem === false) {
$attribs['class'] = $page->getClass();
//}
Run Code Online (Sandbox Code Playgroud)
第5步
添加一个方法将CSS类名应用于<li>标记,因为我们删除了该$addClassTolistItem方法.我们只是使用Page classes功能来拥有自定义属性并执行以下操作:
受保护的函数renderNormalMenu
// Is page active?
if ($isActive) {
$liClasses[] = 'active';
}
if($wrapClass = $page->get('wrapClass')){
$liClasses[] = $wrapClass;
}
...
Run Code Online (Sandbox Code Playgroud)
现在,在我们的Navigation配置文件中,我们可以简单地添加一个名为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',
...
),
...
),
),
...
Run Code Online (Sandbox Code Playgroud)
第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;
}
Run Code Online (Sandbox Code Playgroud)
在配置文件中,您现在可以添加具有其他属性数组的属性:
配置\自动加载\ 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',
...
),
...
),
),
...
Run Code Online (Sandbox Code Playgroud)
第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;
Run Code Online (Sandbox Code Playgroud)
原始代码基本上说"如果这是第一个<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',
...
),
...
),
),
...
Run Code Online (Sandbox Code Playgroud)
需要注意的是,UL类需要放在子节点的第一个子页面上,因为条件语句包含在以下条件中:
if ($depth > $prevDepth) {
// start new ul tag
...
}
Run Code Online (Sandbox Code Playgroud)
调用第一个子节点后,$ dept = $ prevDepth和嵌套<ul>将已经发送到字符串缓冲区.
这个解决方案还没有经过严格的测试,但想法是简单地使用当前的菜单视图助手,并重载两个必要的方法,只是略微修改它.
我试图使用,setPartial()但这只对这<li>一代有所帮助,它仍然使用菜单视图助手的htmlify()方法(所有这些都在Bram上面的讨论中提到过).
因此,与使这些小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>
Run Code Online (Sandbox Code Playgroud)
我遇到的麻烦是更好地理解PHP命名空间,并且需要在我的自定义View Helper中包含适当的Qualified名称空间,即使我正在扩展它.
另一个问题是导航视图助手可以像这样调用菜单视图助手:
$this->navigation('navigation')->menu();
Run Code Online (Sandbox Code Playgroud)
这不起作用:
$this->navigation('navigation')->NewMenu();
Run Code Online (Sandbox Code Playgroud)
我正在考虑因为NewMenu没有在Navigation View Helper类中注册的命名空间问题,我不打算仅为此扩展它.
因此,希望这个(长期)答案将帮助那些正在努力满足这一需求的人.
干杯!
Bra*_*sen 10
该页面类具有共同属性(一些专门制定者setLabel,setId,setUri等),如果不制定者存在__set将被调用.有关此内容以及有关扩展课程的详细信息,请参阅手册AbstractPage.
array(
'label' => 'Page 1',
'id' => 'home-link',
'uri' => '/',
'data-test' => 'blahblah'
),
Run Code Online (Sandbox Code Playgroud)
现在你可以做$page->get('data_test'),它将返回blahblah.
第二个问题是改变菜单的渲染(向liZF2 添加一个属性.ZF2正在使用菜单视图助手来渲染导航菜单.所有导航视图助手都可以选择使用您自己的局部视图进行渲染setPartial().
在你的意见中:
$partial = array('menu.phtml', 'default');
$this->navigation()->menu()->setPartial($partial);
echo $this->navigation()->menu()->render();
Run Code Online (Sandbox Code Playgroud)
在您的局部视图中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>
Run Code Online (Sandbox Code Playgroud)
这只会呈现菜单的最高级别.如果您有更深层/嵌套的结构,您的自定义视图脚本将会变得更加复杂.
希望这可以帮助.
| 归档时间: |
|
| 查看次数: |
9300 次 |
| 最近记录: |