I tried to create a Web Content with a Template that contains the navigation (list of pages):
<nav id="navigation">
<ul>
<#list nav_items as nav_item>
<#assign nav_item_css_class = "" />
<#if nav_item.isSelected()>
<#assign nav_item_css_class = "selected" />
</#if>
<li class="${nav_item_css_class}">
${nav_item.getName()}
<#if nav_item.hasChildren()>
<ul class="child-menu">
<#list nav_item.getChildren() as nav_child>
<#assign nav_child_css_class = "" />
<#if nav_item.isSelected()>
<#assign nav_child_css_class = "selected" />
</#if>
<li class="${nav_child_css_class}">
${nav_child.getName()}
</li>
</#list>
</ul>
</#if>
</li>
</#list>
</ul>
</nav>
But I get this error:
Expression nav_items is undefined
In my theme navigation.ftl it works but in the WCM ftl (FreeMarker) doesn't work.
Then, how can I get the list of pages in WCM?
The list of pages is available only in ADTs (Application Display Templates), not in WCM templates.
If you really need the list and can use ADTs, use navItems variable instead. The variable nav_items only works in themes (for backward compatibility, I guess).
Documentation - hard to find. Use the force, read the source - on GitHub.
You may want to use a handy Freemarker script to display all available variables - see Dumping ADT+WCM Template Variables on James Falkner's blog.
Related
I read that I can set a default content to display in a portlet into the theme layout, with this code:
<#assign VOID = freeMarkerPortletPreferences.setValue("portletSetupPortletDecoratorId", "barebone") />
<#assign VOID = freeMarkerPortletPreferences.setValue("groupId", "37295") />
<#assign VOID = freeMarkerPortletPreferences.setValue("articleId", "46616") />
<#liferay_portlet["runtime"]
defaultPreferences="${freeMarkerPortletPreferences}"
instanceId="quick_links"
portletName="com_liferay_journal_content_web_portlet_JournalContentPortlet"/>
but when I did this, the portlet display that I need set a web content to display:
I have hardcode the groupId because the web content that I want display was created on another site.
I think you have a typo... check this example (https://dev.liferay.com/pt/develop/tutorials/-/knowledge_base/7-0/applying-portlet-decorators-to-embedded-portlets)
<#assign VOID =
freeMarkerPortletPreferences.setValue("portletSetupPortletDecoratorId",
"barebone")>
<div aria-expanded="false" class="collapse navbar-collapse"
id="navigationCollapse">
<#if has_navigation && is_setup_complete>
<nav class="${nav_css_class} site-navigation"
id="navigation" role="navigation">
<div class="navbar-form navbar-right" role="search">
<#liferay.search default_preferences=
"${freeMarkerPortletPreferences}" />
</div>
<div class="navbar-right">
<#liferay.navigation_menu default_preferences=
"${freeMarkerPortletPreferences}" />
</div>
</nav>
</#if>
</div>
<#assign VOID = freeMarkerPortletPreferences.reset()>
I've got a structure for my template for creating web content.
Parent element of text named List and it has got repeatable child element named Item.
When I try to add two or more elements, I can't show them all with my template. It shows only first element of Item.
Here is my template
<#if Information.getSiblings()?has_content>
<#list Information.getSiblings() as information>
<h1>${information.getChild('Title').getData()}</h1>
<p>${information.getChild('Description').getData()}</p>
<ul>
<#list information.getChild('List').getSiblings() as item>
<li>${item.getChild('Item').getData()}</li>
</#list>
</ul>
</#list>
UPD
Deal with it. This is will display all items in list
<#if Information.getSiblings()?has_content>
<#list Information.getSiblings() as information>
<h1>${information.getChild('Title').getData()}</h1>
<p>${information.getChild('Description').getData()}</p>
<ul>
<#list information.getChild('List').getChild('Item').getSiblings() as item>
<li>${item.getData()}</li>
</#list>
</ul>
</#list>
I think you should navigate the Information structure using getChildren() instead of getSiblings()
Something like
<#if parent.getChildren()?has_content>
<#list parent.getChildren() as information>
...
</#list>
</#if>
Using getSiblings() you are missig one of the "brothers"
Within my Liferay 6.2 EE Webcontent template i have the following freemarker code:
<#list teaserHeader.getSiblings() as teaser_header>
<#if getterUtil.getBoolean(teaser_header.teaserVisible.getData())>
<h2 class="section-headline">${teaserHeader.getData()?html}</h2>
<div class="inner-15">
<div class="general-wrapper inner-15-content bound" >
<#if teaser_header.teaserImage.getData() != "">
<div class="product-image-wrapper left">
<img src="${teaser_header.teaserImage.getData()}" width="" height=""/>
</div>
</#if>
<div class="product-teaser-info left">${teaser_header.teaserContent.getData()}</div>
<div class="clearfix"></div>
</div>
</div>
</#if>
</#list>
Unfortunately we have to switch to Velocity.
What's the best approach to transform freemarkers list tag to Velocity ?
I already adopted everything else (if tags, method calls, ...)
But i have some troubles with the list tag.
I tried to do it with foreach in Velocity but i failed...
Thanks
In velocity it should look something like this:
#if (!$teaserHeader.getSiblings().isEmpty())
#foreach ($teaser_header in $teaserHeader.getSiblings())
...
#end
#end
I have created and ADT (Application Display Template) for Asset Publisher which displays web-contents. If a link is clicked the web-content should open in maximized mode.
<#if entries?has_content>
<#list entries as entry>
<#assign renderer = entry.getAssetRenderer() />
<#assign className = renderer.getClassName() />
<#if className == "com.liferay.portlet.journal.model.JournalArticle">
<#assign journalArticle = renderer.getArticle() />
<#assign document = saxReaderUtil.read(journalArticle.getContentByLocale(locale.toString())) />
<#assign assetURL = assetPublisherHelper.getAssetViewURL(renderRequest, renderResponse,entry) />
<div class="molisana-product">
<a href="${assetURL}">
<h3 class="product-title">
${entry.getTitle(locale)}
</h3>
</a>
</div>
</#if>
</#list>
</#if>
The important bit is :
<#assign assetURL = assetPublisherHelper.getAssetViewURL(renderRequest, renderResponse,entry) />
I tried with setWindowState <a href="${assetURL.setWindowState(WindowState.MAXIMIZED)}"> but doesn't work.
I have content with a structure and a template and I want to access the tags of the content to show it in the template.
In a previous Application Display Template of an Asset Publisher, i got the tags with the ServiceLocator like this:
<#list entries as entry>
<#assign assetEntryLocalService = serviceLocator.findService("com.liferay.portlet.asset.service.AssetEntryLocalService") />
<#assign assetTagLocalService = serviceLocator.findService("com.liferay.portlet.asset.service.AssetTagLocalService") />
<#assign assetTags = assetTagLocalService.getEntryTags(entry.getEntryId()) />
<#list assetTags as tag>
<#if tag.getName() != "startseite">
${tag.getName()}
</#if>
</#list>
</#list>
In my Template, I swapped entry with .vars['reserved-article-id'].data but then I get an error:
Method public final java.util.List com.sun.proxy.$Proxy562.getEntryTags(long) throws com.liferay.portal.kernel.exception.SystemException threw an exception when invoked on com.liferay.portlet.asset.service.impl.AssetTagLocalServiceImpl#6bc73e2b
How do you get this to work in a template?
Tags are associated with the assetEntry using it's resourcePrimKey, so you can do this:
<#assign assetEntryLocalService = serviceLocator.findService("com.liferay.portlet.asset.service.AssetEntryLocalService") />
<#assign journalArticleLocalService = serviceLocator.findService("com.liferay.portlet.journal.service.JournalArticleLocalService") />
<#assign article = journalArticleLocalService.getArticle(getterUtil.getLong(scopeGroupId), .vars['reserved-article-id'].data)>
<#assign asset = assetEntryLocalService.getEntry('com.liferay.portlet.journal.model.JournalArticle', article.resourcePrimKey) >
<#list asset.getTags() as tag>
<code>${tag.name}</code>
</#list>
As of Liferay 7, you should be able to use the following:
<#list entries as entry>
<#assign
entry = entry
/>
<#list entry.tagNames as tag>
${tag}
</#list>
</#list>