I was wondering, what is the best way to change the "current" class to be "active" so Bootstrap will work correctly with it?
I thought about copying and overriding the knp_menu_html.twig but i think its not the best way...
Anyway better doing it?
To apply default options in all your application, you can set the knp_menu.renderer.twig.options parameter like this:
// app/config/services.yml
parameters:
knp_menu.renderer.twig.options:
currentClass: active
Default options of the Knp\Menu\Renderer\TwigRenderer are:
$this->defaultOptions = array_merge(array(
'depth' => null,
'matchingDepth' => null,
'currentAsLink' => true,
'currentClass' => 'current',
'ancestorClass' => 'current_ancestor',
'firstClass' => 'first',
'lastClass' => 'last',
'template' => $template,
'compressed' => false,
'allow_safe_labels' => false,
'clear_matcher' => true,
'leaf_class' => null,
'branch_class' => null,
), $defaultOptions);
You can pass it like that:
{{ knp_menu_render('AcmeDemoBundle:Builder:mainMenu', {'currentClass': 'active'}) }}
Related
We've a Drupal 9 installation and are trying to add a pager using the pagerer module for articles entityQuery, the aim is to list tagged articles in a tag page, but it’s not working. It returns null.
When we dump the data without the pager, using default drupal query, it returns the data of all tagged articles properly.
The code is added in the theme file themeName_preprocess_page hook and being called in page--page.html.twig template file.
Here’s our code:
$query = \Drupal::entityQuery('node')
->condition('status', 1)
->condition('type', 'article');
->pager(2);
$nids = $query->sort('created', 'DESC')
->execute();
if($nids):
$nodesNews = \Drupal\node\Entity\Node::loadMultiple($nids);
$pathNews = base_path();
$pager = [
'articles_data' => $nodesNews,
'results' => [
'#theme' => 'news_pagination',
'#items' => $nodesNews,
'#path' => $pathNews,
'#tag' => $tag
],
'pager' => [
'#type' => 'pager',
'#quantity' => 5
],
];
return $pager;
endif;
And here is the code that calls the query:
<div>
{{ articles_data }}
{{ pager }}
</div>
The above code returns only one page in the navigation and we’ve 10 articles, so given that we set 2 articles per page, the output should be 5 pages instead of 1.
Also articles_data attribute returns null. Could you please help me to find what’s wrong with the code? Happy to share more information as needed, thank you.
Just reading the docs for this module here,
it would seem that you are missing at least the #theme and #style keys in your render array for the pager.
A more likely to succeed version of the above render array would be
$pager = [
'articles_data' => $nodesNews,
'results' => [
'#theme' => 'news_pagination',
'#items' => $nodesNews,
'#path' => $pathNews,
'#tag' => $tag
],
'pager' => [
'#type' => 'pager',
'#theme' => 'pagerer_base',
'#style' => 'standard',
'#config' => [
'display_restriction' => 0,
],
'#quantity' => 5
],
];
From the default knp menu bundle template:
{%- elseif matcher.isAncestor(item, options.matchingDepth) %}
{%- set classes = classes|merge([options.ancestorClass]) %}
options.ancestorClass is equal to 'current_ancestor'. Is there a way to override this? I dont want to copy the wohle block item code which covers 50 lines of code, from which I only need to change one value.
To apply default options in all your application, you can set the knp_menu.renderer.twig.options parameter like this:
// app/config/services.yml
parameters:
knp_menu.renderer.twig.options:
currentClass: active
Default options of the Knp\Menu\Renderer\TwigRenderer are:
$this->defaultOptions = array_merge(array(
'depth' => null,
'matchingDepth' => null,
'currentAsLink' => true,
'currentClass' => 'current',
'ancestorClass' => 'current_ancestor',
'firstClass' => 'first',
'lastClass' => 'last',
'template' => $template,
'compressed' => false,
'allow_safe_labels' => false,
'clear_matcher' => true,
'leaf_class' => null,
'branch_class' => null,
), $defaultOptions);
Try
{{ knp_menu_render('AcmeDemoBundle:Builder:mainMenu', {'ancestorClass': 'your-class'}) }}
From this link
I want to render an HTML label like:
$menu->addChild('Dashboard', array(
'route' => 'dashboard',
'label' => '<i class="fa-icon-bar-chart"></i><span class="hidden-tablet"> Dashboard</span></a>',
'extra' => array('safe_label' => true)
)
);
And I've pass the proper option while rendering:
{{ knp_menu_render('WshCmsHtmlBundle:Builder:mainMenu', {'allow_safe_labels': true} ) }}
But my label is still being escaped. What am I doing wrong?
Ok, the answer is!
You set up extra items on menu item not by 'extra' key but by 'extras' key.
So when you setup the item like this:
$menu->addChild('Dashboard', array(
'route' => 'dashboard',
'label' => '<i class="fa-icon-bar-chart"></i><span class="hidden-tablet"> Dashboard</span></a>',
'extras' => array('safe_label' => true)
)
);
it works fine!
There's two steps to achieve this.
1. MenuBuilder
You have to set safe_label to true in extras. Note that you can now write HTML in your label.
$menu->addChild('Home<i><b></b></i>', array(
'route' => 'homepage',
'extras' => array(
'safe_label' => true
),
));
2. Twig
You have to filter the output of knp_menu_render() so that it prints raw HTML (see documentation).
{{ knp_menu_render('main', {'allow_safe_labels': true}) | raw }}
Warning
Please be aware that this may be dangerous. From the documentation:
Use it with caution as it can create some XSS holes in your application if the label is coming from the user.
I used FyodorX's method to add a strong tag. It works like a charm but I must say that the raw filter is not necessary
I want to use KnpMenu for a current project to handle my navigation tree logic.
I have build a menu tree like this:
use Knp\Menu\Matcher\Matcher;
use Knp\Menu\MenuFactory;
use Knp\Menu\Renderer\ListRenderer;
$factory = new MenuFactory();
$menu = $factory->createItem('my_menu');
$menu->addChild('home', array('uri' => '/', 'label' => 'Home'))
->addChild('about', array('uri' => 'about', 'label' => 'About'));
$cat1 = $menu->addChild('category_1', array('uri' => 'category_1', 'label' => 'Category 1'));
$cat1_1 = $cat1->addChild('category_1_1', array('uri' => 'category_1_1', 'label' => 'Category 1.1'));
$cat1_1->addChild('category_1__1', array('uri' => 'category_1_1_1', 'label' => 'Category 1.1.1'));
$cat1_1->addChild('category_1_1_2', array('uri' => 'category_1_1_2', 'label' => 'Category 1.1.2'))->setCurrent(true);
$cat1->addChild('category_1_2', array('uri' => 'category_1_2', 'label' => 'Category 1.2'));
$renderer = new ListRenderer(new Matcher());
echo $renderer->render($menu);
I was wondering if it is possible to render a folded menu tree where only the currently active menu items are displayed. The other items should not be displayed.
In the documentation I haven't found a way to accomplish this.
Does anyone have a solution?
Thank you
Do you mean that you only want to have the menu 'unfolded' if the parent is active?
If so, then yes, I had the same requirement, and there is a PR open for it here https://github.com/KnpLabs/KnpMenu/pull/85
Currently as it's not merged I am using my branch to replace the tagged KnpMenu in composer.
//composer.json excerpt
...
"repositories": [
{
"type": "vcs",
"url": "git#github.com:catchamonkey/KnpMenu"
}
],
require: {
...
"knplabs/knp-menu": "dev-display_children_if_ancestor_current as 2.0.0",
...
}
...
You then tag the top level item with this behaviour, so to make your category_1 only expand if a child is active (or it is active), you would do
$cat1->setDisplayChildrenIfAncestorCurrent(true);
And this is handled by the twig rendered change here https://github.com/KnpLabs/KnpMenu/pull/85/files#L2R74
How would I go around overriding a theme function with a .tpl file? I know how to override a .tpl file with a theme function but not the other way round. I can't seem to find anywhere that tells me so, so maybe it's not possible or not good practice.
For example if there was a theme function defined in a module called super_results and registered with the theme registry, like the example below, how would I go around overriding it with super_results.tpl.php.
'super_results' => array(
'arguments' => array('title' => NULL, 'results' => NULL, 'votes' => NULL),
),
function modulename_super_results($title, $results,$votes){ output HTML }
The simplest solution would probably be creating a new theming function that uses a template. Something like that should work, disclaimer code is untested.
function my_theme_theme() {
return array(
'overide' => array(
'template' => 'elm-super_results',
'arguments' => array('title' => NULL, 'results' => NULL, 'votes' => NULL),
),
);
}
function my_theme_super_results($title, $results, $votes) {
return theme('overide', $title, $results, $votes);
}