9

カスタム属性を Zend Framework 2 ナビゲーションに追加するにはどうすればよいですか?
IDまたはクラスを追加できることは知っています->しかし、それだけです....

data-test='blahblah'1)たとえば、どのように属性を追加しますか? 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をそれにオーバーライドする必要がありますか?

4

3 に答える 3

25

Bramの回答は、私が必要としていたものと解決方法を示しています(私はZF2と名前空間が初めてだったので、必要以上に時間がかかったので、これが他の人に役立つことを願っています)

問題

  • Zend\NavigationそのisActive()メソッドと組み込みの変換、ACL などのサポートを活用して使用したい。
  • <li>要素 要素に CSS クラス名を追加する必要がありました<a>。(ZF2 のメニュー ビュー ヘルパーは現在、「どちらか一方」のアプローチをサポートしています)
  • ネストされた<ul>要素に CSS クラス名を追加する必要がありました。
  • <a>次のような追加の属性を要素に追加する必要がありましたdata-*="..."
  • Bootstrap 3 マークアップをサポートするには、これらの変更が必要でした

ソリューションの説明

  • 拡張して顧客ビュー ヘルパーを作成するZend\View\Helper\Navigation\Menu
  • renderNormalMenu()および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(...){}
}

ステップ2

に新しい View Helper を登録しgetViewHelperConfig()ました\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

私のlayout.phtmlスクリプトでは、Navigation コンテナーを取得し、それを NewMenu ビュー ヘルパーに渡します。また、親<ul>クラス名を追加し、ラベルをエスケープしないなどのオプションを設定して、Bootstrap が使用する標準の「ドロップダウン キャレット」(つまり<b class="caret"></b>) をドロップダウン メニュー付きのラベルに追加できるようにします。

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

休憩

この時点で、Menu View Helper をほぼ複製したはずです。標準の 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 クラスの機能を使用してカスタム プロパティを設定し、次のようにします。

保護された関数 renderNormalMenu

// Is page active?
if ($isActive) {
    $liClasses[] = 'active';
}

if($wrapClass = $page->get('wrapClass')){
    $liClasses[] = $wrapClass;
}
...

wrapClassここで、Navigation 構成ファイルに、 CSS クラスをラッピング要素 ( ) に適用するために呼び出されるプロパティを追加するだけ<li>です。

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
            'pages' => array(
                array(
                    'label' => 'Cars',
                    'route' => 'products/type',
                    ...
                ),
                ...
            ),
        ),
...

ステップ 6

<a>likeに追加の属性を持つ機能を追加します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;
}

構成ファイルで、追加の属性の配列を持つプロパティを追加できるようになりました。

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',
                    ...
                ),
                ...
            ),
        ),
...

ステップ 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>されたものは既に文字列バッファーに送信されています。


このソリューションは厳密にはテストされていませんが、現在のメニュー ビュー ヘルパーを単純に取得し、必要な 2 つのメソッドをオーバーロードし、それをわずかに変更するだけという考え方です。

私は使用しようとしましたが、それは生成にsetPartial()役立つだけでし<li>た.メニュービューヘルパーのhtmlify()メソッドをまだ使用していました.

したがって、これらの小さな調整を to メソッドに加え、Page クラスのカスタム プロパティを持つ機能を使用することで、いくつかの追加ロジックを追加して<li><a>およびネストされたクラスのクラス名を取得し、要素に<ul>追加のプロパティを追加することができたので、 config から<a>myZend\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 名前空間をよりよく理解することと、カスタム ビュー ヘルパーを拡張していたとしても、適切な限定名前空間を含める必要があることでした。

もう 1 つの問題は、Navigation View Helper が次のように Menu View Helper を呼び出すことができることです。

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

これはうまくいきません:

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

Navigation View Helper クラスに登録されていないという名前空間の問題が原因で考えてNewMenuいます。そのためだけに拡張するつもりはありません。

したがって、うまくいけば、この (長い) 回答が、この必要性に苦しんでいる他の人に役立つことを願っています.

乾杯!

于 2013-09-07T00:06:14.933 に答える
10

Page クラスには、共通の属性 ( 、setLabelなど)用の専用のセッターがいくつかあります。セッターが存在しない場合は、が呼び出されます。これに関する詳細とクラスの拡張については、マニュアルを参照してください。setIdsetUri__setAbstractPage

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

これで実行でき$page->get('data_test')、ブラブラが返されます。

li2 番目の質問は、メニューのレンダリングの変更に関するものです ( 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>

これにより、メニューの最上位レベルのみがレンダリングされます。より深い/ネストされた構造がある場合、カスタム ビュー スクリプトははるかに複雑になります。

お役に立てれば。

于 2013-02-23T10:03:52.840 に答える
1

jmbertucciコメントに加えて

問題

ラベルに余分なキャレット タグがあると、次のような問題が発生します。

  • パン粉
  • メニュー翻訳

スプリューション

タグキャレットをラベルに追加しないようにするには、メニュー構成でこのパラメーターのサポートを追加できます。あなたがすべき

に行く

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',

追伸。jmbertucci、あなたは男です。

于 2014-05-05T18:49:35.780 に答える