The following has evaluated to null or missing:
==> structuredContent.taxonomyCategoryBriefs [in template "8911408109993434201#23484949#LEARN-ARTICLE" at line 56, column 34]
----
Tip: It's the step after the last dot that caused this error, not those before it.
----
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: taxonomyCategoryBriefs = structuredCo... [in template "8911408109993434201#23484949#LEARN-ARTICLE" at line 56, column 9]
----
1<@liferay_aui.script>
2 const _addEventListener = (selectors) => {
3 var elements = document.querySelectorAll(selectors);
4
5 elements.forEach((element) => {
6 element.addEventListener("click", (event) => {
7 event.preventDefault();
8
9 const anchorElement = document.getElementById(element.getAttribute("id").replace("toc-", ""));
10
11 if (anchorElement) {
12 window.history.pushState(
13 {},
14 "",
15 "#" + element.getAttribute("id").replace("toc-", "")
16 );
17 scrollToElement(anchorElement);
18 }
19 });
20 });
21 }
22
23 const scrollToElement = (element) => {
24 if (!element) return;
25
26 window.scrollTo({
27 behavior: "smooth",
28 top: element.getBoundingClientRect().top + window.scrollY - 190,
29 });
30 };
31
32 window.addEventListener('load', function() {
33 _addEventListener("h1 a, h2 a, h3 a");
34 _addEventListener(".toc li a");
35
36 if (window.location.hash) {
37 const hashLocation = document.getElementById(window.location.hash.substring(1));
38
39 if (hashLocation) {
40 setTimeout(() => {
41 scrollToElement(hashLocation);
42 }, 100);
43 }
44 }
45 });
46 </@>
47
48<#assign
49 journalArticleId = .vars["reserved-article-id"].data
50
51 structuredContent = restClient.get("/headless-delivery/v1.0/sites/${groupId}/structured-contents/by-key/${journalArticleId}?nestedFields=embeddedTaxonomyCategory")
52
53 showChildrenCards = showChildrenCards.getData()?boolean
54 taxonomyCategoriesMap = {}
55 taxonomyVocabularies = []
56 taxonomyCategoryBriefs = structuredContent.taxonomyCategoryBriefs
57
58 navigationJSONObject = jsonFactoryUtil.createJSONObject(htmlUtil.unescape(navigation.getData()?trim))
59
60 breadcrumbJSONArray = navigationJSONObject.getJSONArray("breadcrumb")
61 childrenJSONArray = navigationJSONObject.getJSONArray("children")
62/>
63
64<#list taxonomyCategoryBriefs as taxonomyCategoryBrief>
65 <#assign taxonomyVocabularyName = taxonomyCategoryBrief.embeddedTaxonomyCategory.parentTaxonomyVocabulary.name />
66
67 <#if !taxonomyVocabularies?seq_contains(taxonomyVocabularyName)>
68 <#assign taxonomyVocabularies = taxonomyVocabularies + [taxonomyVocabularyName] />
69 </#if>
70
71 <#if taxonomyCategoriesMap[taxonomyVocabularyName]?has_content>
72 <#assign taxonomyCategoriesMap = taxonomyCategoriesMap +
73 {
74 taxonomyVocabularyName:
75 taxonomyCategoriesMap[taxonomyVocabularyName] + [{
76 "categoryId": taxonomyCategoryBrief.taxonomyCategoryId,
77 "categoryName": taxonomyCategoryBrief.taxonomyCategoryName
78 }]
79 }
80 />
81 <#else>
82 <#assign taxonomyCategoriesMap = taxonomyCategoriesMap +
83 {
84 taxonomyVocabularyName:
85 [{
86 "categoryId": taxonomyCategoryBrief.taxonomyCategoryId,
87 "categoryName": taxonomyCategoryBrief.taxonomyCategoryName
88 }]
89 }
90 />
91 </#if>
92</#list>
93
94<article class="learn-article">
95 <div class="d-flex flex-column">
96 <div class="learn-article-wrapper">
97 <div class="language-log learn-article-content">
98 <#if (content.getData())??>
99 ${content.getData()}
100 </#if>
101
102 <#if showChildrenCards && childrenJSONArray.length() gt 0>
103 <div class="learn-card-container">
104 <#list 0..childrenJSONArray.length()-1 as i>
105 <#assign childJSONObject = childrenJSONArray.getJSONObject(i) />
106
107 <div class="learn-card">
108 <a href="${childJSONObject.getString("url")}">
109 <h4>${childJSONObject.getString("title")}</h4>
110 </a>
111
112 <#if childJSONObject.getJSONArray("children")?has_content>
113 <#assign grandchildrenJSONArray = childJSONObject.getJSONArray("children") />
114
115 <div class="mt-2 subsection">
116 <#list 0..grandchildrenJSONArray.length()-1 as j>
117 <#assign grandchildJSONObject = grandchildrenJSONArray.getJSONObject(j)! />
118
119 <#if grandchildJSONObject?? && grandchildJSONObject["title"]?has_content && grandchildJSONObject["url"]?has_content>
120 <a href="${grandchildJSONObject["url"]!}">
121 ${grandchildJSONObject["title"]!}
122 </a>
123 </#if>
124 </#list>
125 </div>
126 </#if>
127 </div>
128 </#list>
129 </div>
130 <#else>
131 <div class="learn-article-categories-tags">
132 <#list taxonomyVocabularies as vocabulary>
133 <div class="align-items-baseline d-flex mt-2">
134 <div class="learn-article-category-title mr-2">
135 ${vocabulary}:
136 </div>
137 <#list taxonomyCategoriesMap[vocabulary]?sort_by("categoryName") as taxonomyCategory>
138 <div class="learn-article-category-tag mr-2">
139 <a
140 class="label tag-container"
141 href="/search?${vocabulary?lower_case?replace(" ", "-", "r")}=${taxonomyCategory.categoryId}"
142 >
143 <span>${taxonomyCategory.categoryName}</span>
144 </a>
145 </div>
146 </#list>
147 </div>
148 </#list>
149 </div>
150
151 <div class="article-related-how-to">
152 <#setting url_escaping_charset='UTF-8' />
153
154 <#if (structuredContent.keywords?has_content && structuredContent.keywords?size > 0)>
155 <#assign
156 queryParams = {
157 "fields": "dateModified,id,title",
158 "filter": "(knowledgeArticleType eq 'howTo') and (status eq 0) and (sourceTeam eq 'Enablement')",
159 "pageSize": "3",
160 "search": structuredContent.keywords[0],
161 "sort": "dateModified:desc"
162 }
163 queryParts = []
164 />
165
166 <#list queryParams?keys as key>
167 <#assign
168 value = queryParams[key]
169
170 queryParts = queryParts + ["${key?url}=${value?url}"]
171 />
172 </#list>
173
174 <#assign knowledgeArticles = restClient.get("/c/p2s3knowledgearticles/?" + queryParts?join('&')) />
175
176 <#if (knowledgeArticles.totalCount)?has_content && (knowledgeArticles.totalCount > 0)>
177 <div class="how-to-container">
178 <div class="how-to-container-header">
179 ${languageUtil.get(locale, 'how-to-related-to-this-article')}
180 </div>
181
182 <div class="how-to-cards-container" id="how-to-cards-container">
183 <#list knowledgeArticles.items as knowledgeArticle>
184 <a class="how-to-card" href="${themeDisplay.getPortalURL()}/l/${knowledgeArticle.id}/">
185 <div class="how-to-card-header">
186 ${knowledgeArticle.title}
187 </div>
188
189 <div class="how-to-card-date-published">
190 <#assign date = knowledgeArticle.dateModified?datetime("yyyy-MM-dd'T'HH:mm:ss'Z'")?string("MMM dd, yy HH:mm") />
191
192 ${languageUtil.get(locale, 'published-date')}: ${date}
193 </div>
194
195 </a>
196 </#list>
197 </div>
198 </div>
199 </#if>
200 </#if>
201 </div>
202 </#if>
203 </div>
204 </div>
205 </div>
206</article>
207
208<style>
209 .how-to-card {
210 align-items: flex-start;
211 background: var(--color-brand-primary-lighten-6, #FBFCFE);
212 border: 1px solid var(--color-brand-primary-lighten-5, #E7EFFF);
213 border-radius: 0.75rem;
214 box-sizing: border-box;
215 cursor: pointer;
216 display: flex;
217 flex-direction: column;
218 gap: 0.5rem;
219 isolation: isolate;
220 justify-content: space-between;
221 order: 0;
222 padding: 1rem;
223 width: 100%;
224 }
225
226 .how-to-card:hover {
227 background: var(--color-action-primary-hover-10, #EDF3FE);
228 border: 1px solid var(--color-action-primary-hover, #0053F0);
229 border-radius: 0.625rem;
230 }
231
232 .how-to-card-date-published {
233 align-items: center;
234 align-self: stretch;
235 color: var(--color-neutral-8, #54555F);
236 display: flex;
237 flex: none;
238 flex-grow: 0;
239 font-family: 'Source Sans 3';
240 font-size: 0.75rem;
241 font-style: normal;
242 font-weight: 400;
243 line-height: 1rem;
244 }
245
246 .how-to-card-header {
247 align-items: center;
248 align-self: stretch;
249 color: var(--color-brand-primary, #0B5FFF);
250 display: flex;
251 flex: none;
252 flex-grow: 0;
253 font-family: 'Source Sans 3';
254 font-size: 1rem;
255 font-style: normal;
256 font-weight: 600;
257 line-height: 1.5rem;
258 }
259
260 .how-to-cards-container {
261 display: flex;
262 flex-direction: row;
263 gap: 1rem;
264 width: 100%;
265 }
266
267 .how-to-container {
268 align-items: flex-start;
269 align-self: stretch;
270 background: var(--color-neutral-1, #F7F7F8);
271 border-radius: 0.75rem;
272 display: flex;
273 flex: none;
274 flex-direction: column;
275 flex-grow: 0;
276 gap: 1.5rem;
277 isolation: isolate;
278 margin: 1.5rem 0px;
279 order: 0;
280 padding: 1.5rem;
281 width: 100%;
282 }
283
284 .how-to-container-header {
285 align-items: center;
286 color: var(--color-neutral-10, #282934);
287 display: flex;
288 flex: none;
289 flex-grow: 0;
290 font-family: 'Source Sans 3';
291 font-size: 1.5rem;
292 font-style: normal;
293 font-weight: 700;
294 line-height: 1.75rem;
295 }
296
297 .learn-article {
298 max-width: 900px !important;
299 }
300
301 @media only screen and (max-width: 1200px) {
302 .how-to-cards-container {
303 flex-direction: column;
304 }
305 }
306
307 @media (max-width: 1024px) {
308 .learn-article {
309 margin-top: 2.5rem;
310 }
311 }
312</style>
Capabilities
Product
Education
Knowledge Base
Contact Us