Detailseiten in der Contao-Navigation anzeigen
In dem FE-Modul der Contao-Navigation werden nur die Seiten als Navigationspunkt ausgegeben, die sich auch im Seitenbaum
befinden z. B. /produkte/uebersicht. Möchte man zusätzlich zu den Contao-Seiten auch Detailseiten wie zum Beispiel
/produkt/detail/artikelnummer/1364 anzeigen, obwohl es nur die Seite /produkt/detail im Seitenbaum gibt, kann man
verschiedene Wege dafür gehen.
Eigene Seiten im Seitenbaum mit Alias für Weiterleitung
Wenn es die Seite /produkt/detail als Contao Seite gibt, bei der über die Slugparameter artikelnummer/1364 der
gewünschte Artikel angezeigt wird, kann man eine neue Seite im Seitenbaum an der gewünschten Stelle für die
Navigation einbauen z. B. mit dem Titel „Artikel 1364“. Der Alias der Seite wird aber manuell auf den Alias der
Detailansicht gesetzt /produkt/detail/artikelnummer/1364. Damit beim Aufruf des Navigationslinks für „Artikel 1364“
auch der gewünschte Inhalt angezeigt wird, muss die Seite /produkt/detail eine höhere Routenpriorität (10) als die
Seite artikelnummer/1364 (0) bekommen.
ParseTemplateListener zum Anpassen der Navigation
Mit dem ParseTemplateListener kann das Template
nav_default (oder eigenen Varianten davon) vor der „Auslieferung“ noch manipuliert werden. Damit ist es möglich, an
gewünschter Position eigene Navigationslinks (siehe getSublinks()) einzubauen. Folgend ein Beispielcode:
1<?php
2// src/EventListener/ParseTemplateListener.php
3
4namespace App\EventListener;
5
6use Contao\CoreBundle\DependencyInjection\Attribute\AsHook;
7use Contao\Template;
8use MetaModels\Filter\Setting\IFilterSettingFactory;
9use MetaModels\IFactory;
10use MetaModels\IMetaModel;
11use MetaModels\Render\Setting\IRenderSettingFactory;
12use Symfony\Component\HttpFoundation\RequestStack;
13
14use function sprintf;
15use function str_replace;
16use function trim;
17
18#[AsHook('parseTemplate')]
19class ParseTemplateListener
20{
21 public function __construct(
22 private readonly IFactory $factory,
23 private readonly IFilterSettingFactory $filterFactory,
24 private readonly IRenderSettingFactory $renderFactory,
25 private readonly RequestStack $requestStack,
26 ) {
27 }
28
29 public function __invoke(Template $template): void
30 {
31 if ('nav_default' === $template->getName()) {
32 $levelData = $template->getData();
33
34 // Check only level 1.
35 if ('level_1' !== $levelData['level']) {
36 return;
37 }
38
39 $items = $levelData['items'];
40 foreach ($items as &$item) {
41 // Check only page id 7.
42 if (7 !== ($item['id'] ?? null)) {
43 continue;
44 }
45
46 // Add subitems as level 2 at page id 7 and mark parent as trail.
47 if ([] !== ($subLinks = $this->getSublinks())) {
48 $item['subitems'] = $subLinks['subitems'];
49 $item['class'] =
50 trim(
51 'submenu ' . ($subLinks['trail'] ? str_replace('sibling', 'trail', $item['class']) : '')
52 );
53 }
54 }
55 unset($item);
56 $levelData['items'] = $items;
57
58 $template->setData($levelData);
59 }
60 }
61
62 private function getSublinks(): array
63 {
64 // Begin configuration.
65 $modelName = 'mm_employees';
66 $renderId = 4;
67 $filterId = 3;
68 // End configuration.
69
70 if (!(($model = $this->factory->getMetaModel($modelName)) instanceof IMetaModel)) {
71 return [];
72 }
73
74 $filter = $model->getEmptyFilter();
75 $filterCollection = $this->filterFactory->createCollection($filterId);
76 $filterCollection->addRules($filter, []);
77 $items = $model->findByFilter($filter);
78
79 if (!$items->getCount()) {
80 return [];
81 }
82
83 $parsed = $items->parseAll('text', $this->renderFactory->createCollection($model, $renderId));
84 unset($items, $filterCollection, $filter, $model);
85
86 $request = $this->requestStack->getCurrentRequest();
87 if (null === $request) {
88 return [];
89 }
90 $path = $request->getRequestUri();
91 $isTrail = false;
92 $subLinkList = '<ul class="level_2">';
93 foreach ($parsed as $item) {
94 $href = $item['actions']['jumpTo']['href'];
95 // Possibly clean up the path+href from GET parameters or anchor links.
96 if ($path !== $href) {
97 $subLinkList .= sprintf(
98 '<li><a href="%1$s" title="%2$s">%2$s</a></li>',
99 $href,
100 $item['text']['name']
101 );
102 } else {
103 $isTrail = true;
104 $subLinkList .= sprintf(
105 '<li class="active"><strong class="active" aria-current="page">%s</strong></li>',
106 $item['text']['name']
107 );
108 }
109 }
110 $subLinkList .= '</ul>';
111
112 return ['trail' => $isTrail, 'subitems' => $subLinkList];
113 }
114}
Mehr zum Registrieren von Services in dem verlinkten Artikel.
Erweiterung „hofff/contao-navigation“ und „TreeEvent“
Die Erweiterung „Contao-Navigation“ stellt ein eigenes FE-Modul für
die Navigation zur Verfügung. Zudem hat die Erweiterung verschiedene Events, bei dem die Manipulation der Ausgabe
gegenüber dem ParseTemplateListener eleganter durchzuführen ist. Folgend ein Beispielcode zum Anfügen eines
zusätzlichen Links in der Navigation - das kann aber auch zur Ausgabe von MM-Detailseiten entsprechend angepasst werden.
1<?php
2// src/EventListener/NavigationMenuListener.php
3
4namespace App\EventListener;
5
6use Hofff\Contao\Navigation\Event\TreeEvent;
7use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
8
9use function array_keys;
10
11#[AsEventListener('Hofff\Contao\Navigation\Event\TreeEvent')]
12class NavigationMenuListener
13{
14 public function __invoke(TreeEvent $treeEvent): void
15 {
16 $moduleId = $treeEvent->moduleModel()->id; // Module id for checking if it's the correct module.
17 $pageId = $treeEvent->items()->currentPage->id; // Page id for checking if it's the correct page.
18 $pageItems = $treeEvent->items(); // Get the page items for the navigation tree.
19 $rootIds = $pageItems->roots;
20
21 // Add a new item to the first root as the last one.
22 $pageItems->subItems[array_keys($rootIds)[0]][] = 9999;
23
24 // Item data.
25 $pageItems->items[9999] = [
26 'class' => 'mm-page',
27 'isInTrail' => false,
28 'isActive' => false,
29 'pageTitle' => 'MetaModels',
30 'accesskey' => '',
31 'target' => 'target="_blank"',
32 'link' => 'MetaModels',
33 'href' => 'https://now.metamodel.me',
34 ];
35 }
36}
Mehr zum Registrieren von Services in dem verlinkten Artikel.