Customize the KnpMenuBundle

自古美人都是妖i 提交于 2019-11-27 10:07:33

问题


How to customize KNPMenuBundle?

I can't figure out how to add an image or a span tag using the KnpMenuBundle.

I simply want this:

<ul>
    <li>
         <img src="{{asset('bundles/mybundle/images/my_image.png')}} /">
         <span>My Title</span>        
     </li>
</ul>

In the MenuBuilder, this would start with:

$menu->addChild('My Title');

How could I add the image in the <li> statement?


EDIT: THE EASY WAY

There is actually an easy way to do this within the bundle:

1 Copy the template vendor\KnpMenu\src\Knp\Menu\Resources\views\knp_menu.html.twig into your Acme\AcmeBundle\Resources\views\Menu\knp_menu.html.twig and extend it as follow:

{% extends 'knp_menu.html.twig' %}


2 Modify the template according to your needs. For example, if you decide to add a span tag each time you use $menu->addChild('Your Title');, simply add the span tag between <a></a>:

{% block linkElement %}
    <a href="{{ item.uri }}"{{ _self.attributes(item.linkAttributes) }}>
        <span>{{ block('label') }}</span>
    </a>
{% endblock %}


3 You can now choose your custom layout when using the menu:

{{ knp_menu_render('main', {'template': 'AcmeBundle:Menu:knp_menu.html.twig'}) }}

回答1:


CSS works for this case, but sometimes you might need to add or change the markup more significantly. For that you can use a custom renderer as defined here: https://github.com/KnpLabs/KnpMenuBundle/blob/master/Resources/doc/custom_renderer.md

An example of a bundle that does this is the MopaBoostrapBundle I've highlighted the important parts here.

The service definition where the knp_menu.renderer tag is added:

services:
    mopa_bootstrap.navbar_renderer:
        class: Mopa\Bundle\BootstrapBundle\Navbar\Renderer\NavbarRenderer
        arguments: [ @service_container, [] ]
        tags:
            # The alias is what is used to retrieve the menu
            - { name: knp_menu.renderer, alias: navbar }

and the twig template can be written like so, for example.

<div class="navbar {{ (navbar.hasOption('fixedTop') and  navbar.getOption('fixedTop')) ? 'navbar-fixed-top' : '' }}">
    <div class="navbar-inner">
        <div class="container{{ (navbar.hasOption('isFluid') and navbar.getOption('isFluid')) ? '-fluid' : '' }}">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </a>
            {% if navbar.hasOption('title') %}<a class="brand" href="{{ path(navbar.getOption('titleRoute')) }}">{{ navbar.getOption('title') }}</a>{% endif %}
            <div class="nav-collapse">
                {{ navbar.hasMenu('leftmenu') ? knp_menu_render(navbar.getMenu('leftmenu'), {'currentClass': 'active', 'ancestorClass': 'active', 'allow_safe_labels': 'true'}) : '' }}
                {% if navbar.hasFormView('searchform') %}
                    {%- set form_view = navbar.getFormView('searchform') -%}
                    {%- set form_type = navbar.getFormType('searchform') -%}
                    {%- set form_attrs = form_view.vars.attr -%}
                    {% form_theme form_view _self %}
                    <form class="navbar-search pull-{{ form_attrs.pull|default('left') }}" method="{{ form_attrs.method|default('post') }}" action="{{ path(navbar.getFormRoute('searchform')) }}">
                    {{ form_widget(form_view) }}
                    </form>
                {% endif %}
                {{ navbar.hasMenu('rightmenu') ? knp_menu_render(navbar.getMenu('rightmenu'), {'currentClass': 'active', 'ancestorClass': 'active', 'allow_safe_labels': 'true'}) : '' }}
            </div>

        </div>
    </div>
</div>



回答2:


I spent a while figuring this out.

There is an parameter you can apply when defining the menu item called 'safe_label'. By setting this to true it output the image in the navbar instead of the html.

    $image = "<img src='/path/to/image' />";
    $menu->addChild( $image , 
      array(
        'route' => 'url_route_name',
        'extras' => array(
          'safe_label' => true
        )
      )
    );

Hope that helps




回答3:


You need to import the macros from the parent template before you can use them.

{% block linkElement %}
    {% import 'knp_menu.html.twig' as knp_menu %}
    <a href="{{ item.uri }}"{{ knp_menu.attributes(item.linkAttributes) }}>
        <span>{{ block('label') }}</span>
    </a>
{% endblock %}





回答4:


To simply add classes and other HTML attributes (for example, to integrate the menù with Twitter Bootstrap addind its classes and IDs), you can use the methods provided for that sort of customization.

Here are some useful resources:

  • Here are all the details from KNP Menu Bundle's documentation: Creating Menus: The Basics - Menu attributes
  • Here are some concrete examples: (On GitHub) KNP Menu Bundle with Bootstrap 3 and Font Awesome 4

KnpMenuBundles provides some documented methods like setAttributes, selLinkAttirbute or setLabelAttribute (and other methods too) that are useful to customize the menù rendering.




回答5:


Why not define an attribute of the <li> or <span> element and add the image in css ?



来源:https://stackoverflow.com/questions/11226963/customize-the-knpmenubundle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!