Banner Image Us

How building managers and maintenance providers can work together

READ POST

Otis Elevator Blog

An error occurred while processing the template.
The following has evaluated to null or missing:
==> parentCategories  [in template "20101#20128#369263930" at line 31, column 89]

----
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: ${parentCategories?size}  [in template "20101#20128#369263930" at line 31, column 87]
----
1<#assign hasCategories = false /> 
2<#assign currentLocale = themeDisplay.getLanguageId()?lower_case /> 
3 
4<#if entries?has_content> 
5	<input type="hidden" name="entries" value="${entries?size}" /> 
6	<div class="blog-filter filter_listing_event"> 
7          <div class="blog-filter news_listing_filters"> 
8            <nav id="topicMenu" class=" blog-filter blog-filter-options"> 
9              <div class="blog-filter right_label_filter_accordion"> 
10                <h4> 
11                  <span style="font-size:14px; font-family: Nunito-sans, sans-serif; color:#ffffff; font-weight:bold;"><@liferay_ui.message key="filter-by-topic" /></span> 
12                </h4> 
13              </div> 
14              <div id="right_filter_accordion"> 
15		<#list entries as entry> 
16			<#assign vocabularyId = entry.getVocabularyId() /> 
17			<input type="hidden" name="VocabularyId" value="${vocabularyId}" /> 
18			<#assign categories = entry.getCategories() /> 
19			<input type="hidden" name="categories" value="${categories?size}" /> 
20 
21			<#if serviceLocator??> 
22						<#assign 
23							assetCategoryService = serviceLocator.findService("com.liferay.asset.kernel.service.AssetCategoryLocalService") 
24						/> 
25				</#if>	 
26			<#if assetCategoryService??> 
27						<#assign 
28							parentCategories = assetCategoryService.getVocabularyRootCategories(vocabularyId,-1,-1,null) 
29						/> 
30				</#if>	 
31				  <input type="hidden" name="parentCategories" value="${parentCategories?size}" /> 
32						<@loadParentCategory parentCategories=parentCategories /> 
33					</#list> 
34 
35		<#if !hasCategories> 
36							<label class="blog-filter switch form-check-label d-flex align-items-center justify-content-between px-4 py-5"> 
37                <div class="blog-filter title-text"> 
38                  <span class="blog-filter title"><@liferay_ui.message key="there-are-no-categories" /></span> 
39                </div> 
40              </label> 
41								</#if> 
42	</div> 
43            </nav> 
44          </div> 
45        </div> 
46</#if> 
47 
48<#macro loadParentCategory 
49	parentCategories 
50
51	<#if parentCategories?has_content> 
52			<#list parentCategories as parentCategory> 
53				<#if currentLocale == parentCategory.getName()?lower_case > 
54					<#if serviceLocator??> 
55						<#assign 
56							assetCategoryService = serviceLocator.findService("com.liferay.asset.kernel.service.AssetCategoryService") 
57							childCategories = assetCategoryService.getChildCategories(parentCategory.getCategoryId()) 
58						/> 
59						<#if childCategories?has_content> 
60							<#assign hasCategories = true /> 
61							<@displayCategories childCategories=childCategories /> 
62						</#if> 
63					</#if> 
64				</#if> 
65			</#list> 
66	</#if> 
67</#macro> 
68 
69<#macro displayCategories 
70	childCategories 
71
72	<#if childCategories?has_content> 
73			<#list childCategories as childCategory> 
74					<#assign categoryURL = renderResponse.createRenderURL() /> 
75					${categoryURL.setParameter("resetCur", "true")} 
76					${categoryURL.setParameter("categoryId", childCategory.getCategoryId()?string)} 
77					<label class="blog-filter switch form-check-label d-flex align-items-center justify-content-between px-4" for="${childCategory.getName()}"> 
78           <div class="blog-filter title-text"> 
79               <span class="blog-filter title">${childCategory.getName()}</span> 
80           </div> 
81						<input class="blog-filter form-check-input filter-item" name="category" onChange="handleCategoryFilter(this)" type="checkbox" data-filter="resource" value="${childCategory.getCategoryId()?string}" id="${childCategory.getCategoryId()?string}"> 
82        </label> 
83						<#assign 
84							assetCategoryService = serviceLocator.findService("com.liferay.asset.kernel.service.AssetCategoryService") 
85							childCategories2 = assetCategoryService.getChildCategories(childCategory.getCategoryId()) 
86						/> 
87						<@displayCategories childCategories=childCategories2 /> 
88			</#list> 
89	</#if> 
90</#macro> 
91 
92<script> 
93	function handleCategoryFilter(element){ 
94		console.log("element >>> ",element) 
95		// Get all checked checkboxes (adjust selector as needed) 
96    const checkedCheckboxes = document.querySelectorAll('input[type="checkbox"][name="category"]:checked'); 
97		 
98		checkedCheckboxes.forEach(checkbox=>{ 
99			if(element.id !== checkbox.id){ 
100			  checkbox.checked = false; 
101
102		}) 
103		 
104    let categoryId = ""; 
105		if(element.checked){ 
106		  categoryId = element.value; 
107
108		 
109		// Get current URL parts 
110    const currentUrl = window.location.href; 
111    const urlObj = new URL(currentUrl); 
112    const pathParts = urlObj.pathname.split('/'); 
113		 
114		if(categoryId){ 
115    // Check if categories segment exists 
116    const categoriesIndex = pathParts.findIndex(part => part === 'categories'); 
117  
118   if (categoriesIndex !== -1) { 
119     // Replace existing category IDs 
120     pathParts[categoriesIndex + 1] = categoryId; 
121   } else { 
122     // Add new categories segment 
123     // Find where to insert (before query parameters) 
124     const insertPosition = pathParts[pathParts.length - 1] === '' 
125       ? pathParts.length - 1 
126       : pathParts.length; 
127     pathParts.splice(insertPosition, 0, '-/categories', categoryId); 
128
129		}else{ 
130		 // Check if categories segment exists 
131		 const categoriesIndex = pathParts.findIndex(part => part === 'categories'); 
132		 if (categoriesIndex !== -1) { 
133			 pathParts.splice(categoriesIndex -1); 
134
135
136  
137    // Rebuild the URL 
138    urlObj.pathname = pathParts.join('/'); 
139    const newUrl = urlObj.toString(); 
140  
141    console.log("New URL:", newUrl); 
142    window.location.href = newUrl; // Uncomment to navigate 
143
144 
145	 
146	document.addEventListener('DOMContentLoaded', function() { 
147  // Extract category IDs from URL 
148  const url = new URL(window.location.href); 
149  const pathParts = url.pathname.split('/'); 
150  const categoriesIndex = pathParts.findIndex(part => part === 'categories'); 
151   
152  if (categoriesIndex !== -1 && pathParts.length > categoriesIndex + 1) { 
153    const categoryIds = pathParts[categoriesIndex + 1].split(','); 
154     
155    // Check the corresponding checkboxes 
156    categoryIds.forEach(id => { 
157      const checkbox = document.querySelector('input[type="checkbox"][value="'+id+'"]'); 
158      if (checkbox) { 
159        checkbox.checked = true; 
160      } else { 
161        console.warn('Checkbox with value "'+id+'" not found'); 
162
163    }); 
164     
165    console.log('Checked '+categoryIds.length+' category checkboxes'); 
166  } else { 
167    console.log('No category IDs found in URL'); 
168
169}); 
170	 
171</script> 
172 
173<style> 
174.blog-filter .blog-filter-options { 
175    background-color: #eceae8 
176
177 
178.blog-filter .right_label_filter_accordion { 
179    background-color: #041e42; 
180    padding-left: 20px 
181
182 
183.event-listing-custom .blog-filter .card .blog-filter.article_space .blog-listing__post-button-wrapper { 
184    bottom: 0; 
185    margin: 15px 0 20px; 
186    position: absolute 
187
188 
189.event-listing-custom .blog-filter .card .blog-filter.article_space { 
190    border: 1px solid rgba(0,0,0,.125); 
191    border-radius: .25rem; 
192    height: 100%; 
193    position: relative 
194
195 
196.event-listing-custom .blog-filter .card .blog-filter.article_space .blog-listing__post-content { 
197    padding: 30px 20px 
198
199 
200.event-listing-custom .blog-listing__post-tags a.blog-listing__post-tag { 
201    width: auto!important 
202
203 
204section.blog-filter .container-wrap { 
205    margin: 0 auto; 
206    max-width: 1300px 
207
208 
209.event-listing-custom .blog-filter .card .blog-filter.article_space .featured_image_content { 
210    line-height: 0 
211
212 
213.event-listing-custom .blog-filter .card .blog-filter.article_space .blog-listing__post-content h2.blog-listing__post-title { 
214    margin: 0 
215
216 
217section.blog-filter #products article.blog-filter h2.blog-listing__post-title a { 
218    margin-bottom: 18px; 
219    text-transform: capitalize 
220
221 
222.event-listing-custom .blog-filter .card .blog-filter.article_space a.blog-listing__post-tag { 
223    color: #f65275; 
224    font-weight: 700; 
225    margin-bottom: 15px!important; 
226    text-transform: capitalize 
227
228 
229.event-listing-custom .blog-filter .card .blog-filter.article_space .blog-listing__post-content .blog-listing__post-summary p { 
230    color: #041e42; 
231    line-height: 22px; 
232    margin-bottom: 30px 
233
234 
235.event-listing-custom .blog-filter .card .blog-filter.article_space:hover { 
236    box-shadow: 0 1px 4px rgba(0,0,0,.16); 
237    transition: all .4s ease-in-out 
238
239 
240.right_sort_filter_left label span.blog-filter.right_sort_filter_left_span { 
241    padding-right: 20px 
242
243	 
244#right_filter_accordion .switch.form-check-label { 
245    border-bottom: 1px solid rgb(217, 217, 217); 
246    padding: 15px; 
247
248 
249@media only screen and (max-width: 767px) { 
250     
251    .blog-filter-options.active .right_label_filter_accordion:after { 
252        top: 42%; 
253        transform: rotate(180deg) 
254
255 
256    .Two_column .event-listing-custom .blog-listing .card { 
257        width: 100%!important 
258
259 
260    .article_space .blog-listing__post-button.button { 
261        padding: 10px 22px 
262
263
264 
265h2.entry-title.taglib-categorization-filter { 
266    display: none; 
267
268 
269</style>