BIS: Templatebasierte Anzeige (alt)

Fehler bei der Verarbeitung der Vorlage.
The following has evaluated to null or missing:
==> bundle  [in template "MAKROS" at line 2, column 11]

----
Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
----

----
FTL stack trace ("~" means nesting-related):
	- Failed at: ${bundle}  [in template "MAKROS" at line 2, column 9]
	- Reached through: #import "${templatesPath}/MAKROS" as ...  [in template "63520" at line 5, column 1]
	- Reached through: #include "${templatesPath}/63520"  [in template "20936#20974#164313" at line 7, column 1]
----
1<#-- @ftlvariable name="vr" type="de.regioit.liferay.vr.portlet.bisview.model.adt.AdtVr" --> 
2<#-- ---------------------------------------------- --> 
3<#-- Ansicht Dienstleistungsuebersicht A-Z --> 
4<#-- ---------------------------------------------- --> 
5 
6<#-- Vorlagenschlüssel von bisview-detail --> 
7<#include "${templatesPath}/63520"> 
8 
9<#if ansicht == "bisview-az-verzeichnis-dienstleistung" && azVerzeichnisDienstleistung??> 
10 
11    <#assign categoryList = []> 
12    <#assign categoryIdList = []> 
13 
14    <#list azVerzeichnisDienstleistung?keys as entry> 
15        <#list azVerzeichnisDienstleistung[entry] as k> 
16            <#list k.kategorien as kat> 
17                <#if !categoryIdList?seq_contains(kat.id)> 
18                    <#assign categoryList = categoryList + [kat]> 
19                    <#assign categoryIdList = categoryIdList + [kat.id]> 
20                </#if> 
21            </#list> 
22        </#list> 
23    </#list> 
24    <#assign categoryList = categoryList?sort_by("name")> 
25 
26    <div class="adt-az"> 
27        <h2><@macros.print "or.dienstleistungen" "Dienstleistungen"/></h2> 
28 
29        <p> 
30            <@macros.print "or.dienstleistungen.a-z-liste.infotext" "Hier finden Sie eine Übersicht aller Dienstleistungen. Bitte haben Sie Verständnis dafür, dass Sie für einige Online-Dienstleistungen angemeldet sein müssen."/> 
31        </p> 
32        <div class="w-md-488px w-100"> 
33            <ul class="nav nav-tabs my-2" role="tablist" 
34                <#if !getterUtil.getBoolean(themeDisplay.getThemeSetting("Dienstleistungen_kategorien_tab_anzeigen"), false)>hidden</#if> 
35
36                <li role="presentation" class="active flex-grow-1 text-center"> 
37                    <a href="kategorien" role="tab" aria-selected="false"> 
38                        <i class="glyphicon glyphicon-th" aria-hidden="true"></i> 
39                        <@macros.print "or.lebenslagen" "Lebenslagen"/> 
40                    </a> 
41                </li> 
42                <li role="presentation" class="flex-grow-1 text-center"> 
43                    <a href="dienstleistungen" class="active show" role="tab" aria-selected="true"> 
44                        <i class="glyphicon glyphicon-th-list" aria-hidden="true"></i> 
45                        <@macros.print "or.dienstleistungen" "Dienstleistungen"/> 
46                    </a> 
47                </li> 
48            </ul> 
49 
50            <div class="input-group input-group-filter"> 
51 
52                <div class="suchinput-group"> 
53                    <input id="sucheinput" placeholder="Suchwort eingeben"> 
54                    <div class="suchinput-addon input-group-addon input-group-text"> 
55 
56                        <i class="glyphicon glyphicon-search" aria-hidden="true"></i> 
57                    </div> 
58                </div> 
59            </div> 
60 
61            <div class="category-select-group" 
62                 <#if !getterUtil.getBoolean(themeDisplay.getThemeSetting("Dienstleistungen_kategorien_anzeigen"), true)>hidden</#if> 
63
64                <select id="category-select"> 
65                    <option value=""><@macros.print "or.dienstleistungen.a-z-liste.lebenslage-auswaehlen" "Lebenslage auswählen..."/></option> 
66                    <#list categoryList as kat> 
67                        <option value="${kat.name}">${kat.name}</option> 
68                    </#list> 
69                </select> 
70 
71                <div class="category-info"> 
72                    <span class="category-info-questionmark">?</span> 
73                    <div class="category-info-box hidden"> 
74                        <div class="category-info-box-closer"><i class="glyphicon glyphicon-remove" aria-hidden="true"></i></div> 
75                        <@macros.print "or.dienstleistungen.a-z-liste.lebenslage-wechseln" "Sie können hier die Lebenslage wechseln oder alle verfügbaren Leistungen anzeigen lassen."/> 
76                    </div> 
77                </div> 
78            </div> 
79        </div> 
80        <br/> 
81 
82        <div id="dl-accordion"> 
83            <div class="row"> 
84                <#list azVerzeichnisDienstleistung?keys as entry> 
85                    <div class="col-xs-2 col-sm-1 mb-3 text-center listletter letter-select" data-letter="${entry}"> 
86                        <a href="#list-${entry}" aria-controls="list-${entry}">${entry}</a> 
87                    </div> 
88                </#list> 
89            </div> 
90 
91            <hr class="bg-primary h-1"> 
92 
93            <#list azVerzeichnisDienstleistung?keys as entry> 
94                <div id="list-${entry}" class="collapse show letterlistelement listletter" data-parent="#dl-accordion" data-letter="${entry}"> 
95                    <ul class="list-group list-group-flush"> 
96                        <h3 class="letter" name="letter-${entry}" data-letter="${entry}"><span>${entry}</span></h3> 
97                        <#list azVerzeichnisDienstleistung[entry] as k> 
98 
99                            <#assign url = utils.getDienstleistungUrl(k.id)> 
100                            <li class="list-group-item dlitem" data-letter="${entry}" data-kategorie="<#list k.kategorien as kat>${kat.name},</#list>" data-synonyme="${k.synonyme}"> 
101                                <a href="${url}" title="<@macros.print "or.aktion.details-anzeigen" "Details anzeigen"/>">${k.name}</a> 
102                            </li> 
103 
104                        </#list> 
105                    </ul> 
106                </div> 
107            </#list> 
108        </div> 
109    </div> 
110 
111 
112    <script> 
113 
114        function updateParams(text, kat) { 
115            const url = new URL(window.location); 
116            url.searchParams.set('search', text); 
117            url.searchParams.set('kategorie', kat); 
118            window.history.replaceState({}, '', url); 
119
120 
121        function filter(suchtext, katName) { 
122            if (katName.length > 0 || suchtext.length > 0) { 
123 
124                const letters = []; 
125 
126                Array.from(document.getElementsByClassName('listletter')).forEach(element => element.classList.remove("hidden")); 
127                Array.from(document.getElementsByClassName('letterlistelement')).forEach(element => element.classList.remove("show")); 
128                Array.from(document.getElementsByClassName('dlitem')).forEach(function (element) { 
129                    const kategorieIds = element.dataset.kategorie; 
130                    const synonyme = element.dataset.synonyme; 
131                    const text = element.getElementsByTagName('a').item(0)?.textContent; 
132 
133                    if (kategorieIds.toLowerCase().includes(katName.toLowerCase()) 
134                        && (text.toLowerCase().includes(suchtext.toLowerCase()) || synonyme.toLowerCase().includes(suchtext.toLowerCase())) 
135                    ) { 
136                        element.classList.remove("hidden"); 
137                        element.parentElement.parentElement.classList.remove("hidden"); 
138                        element.parentElement.parentElement.classList.add("show"); 
139                        letters.push(element.dataset.letter); 
140                    } else { 
141                        element.classList.add("hidden"); 
142
143                }); 
144 
145                Array.from(document.getElementsByClassName('letter-select')).forEach(element => element.classList.add("hidden")); 
146                letters.forEach(l => { 
147                    Array.from(document.querySelector(".letter-select[data-letter='" + l + "']")).forEach(element => element.remove("hidden")); 
148                }) 
149 
150            } else { 
151                Array.from(document.getElementsByClassName('listletter')).forEach(element => element.classList.remove("hidden")) 
152                Array.from(document.getElementsByClassName('dlitem')).forEach(element => element.classList.remove("hidden")) 
153                Array.from(document.getElementsByClassName('letterlistelement')).forEach(element => element.classList.add("show")) 
154                Array.from(document.getElementsByClassName('letter-select')).forEach(element => element.classList.remove("hidden")) 
155
156
157 
158        document.getElementById("sucheinput").addEventListener("input", () => { 
159            searchOrKategoryChanged(); 
160        }); 
161        document.getElementById("category-select").addEventListener("change", () => { 
162            searchOrKategoryChanged(); 
163        }); 
164 
165        function searchOrKategoryChanged() { 
166            const suchtext = document.getElementById("sucheinput").value || ""; 
167            const category = document.getElementById("category-select").value || ""; 
168            updateParams(suchtext, category); 
169            filter(suchtext, category); 
170
171 
172 
173        function init() { 
174            const suchtext = new URLSearchParams(window.location.search).get("search") || ""; 
175            document.getElementById("sucheinput").value = suchtext; 
176 
177            const kategorieParam = new URLSearchParams(window.location.search).get("kategorie") || ""; 
178            const select = document.getElementById("category-select"); 
179            const options = select.options; 
180            Array.from(options).forEach(option => { 
181                if (option.value === kategorieParam) { 
182                    select.value = option.value; 
183
184            }); 
185            filter(suchtext, kategorieParam); 
186
187 
188        init(); 
189    </script> 
190 
191</#if>