I am using the below code in ADT custom template code
<#assign storageEngineUtil = utilLocator.findUtil("com.liferay.portlet.asset.service.AssetEntryLocalServiceUtil") />
But this is giving utilLocator.findUtil("com.liferay.portlet.asset.service.AssetEntryLocalServiceUtil") is undefined
Is there anything I'm missing here?
but
The util class AssetEntryLocalServiceUtil is not accessible from a Freemarker template.
What you're trying to do is to get access to AssetEntryLocalService. Access to Liferay services is restricted in ADT templates.
You can get instance to AssetEntryLocalService through ServiceLocator, but you have to tell Liferay to allow it.
Default configuration restricts access to serviceLocator variable (in portal.properties).
#
# Set a comma delimited list of variables the FreeMarker engine cannot
# have access to. This will affect Dynamic Data List templates, Journal
# templates, and Portlet Display templates.
#
freemarker.engine.restricted.variables=serviceLocator
The setting needs to be overridden to empty value in portal-ext.properties (ie. allow the usage of serviceLocator in templates).
Then you can finally call serviceLocator.findService to get the service.
<#assign assetEntryLocalService = serviceLocator.findService("com.liferay.portlet.asset.service.AssetEntryLocalService") />
Related
We're using Liferay 7.3 (CE) and are trying to embrace the relatively new feature of "Content Pages" with "Page Fragments". We're able to develop page fragments that already include portlets (named "widgets" in the context of content pages), using the <lfr-widget-WIDGETALIAS> tag. So far, that works.
Now we're trying to prepare page fragments that embed portlets with special portlet configuration applied. For example, we want to prepare a page fragment that just shows an asset publisher portlet configured to list WebContent articles from a pre-defined category. The user should be able to just put that fragment onto the page without having to care about the configuration of the asset publisher portlet.
We did not find any direct way to achieve that -- our first guess that the configuration could be written as attributes or content of the <lfr-widget-...> tag was deterred by a hint in the liferay docs that there are no valid attributes or content to attach to that tag.
Does anybody have an inkling of an idea on how to achieve embedding portlets in page fragments with pre-defined portlet configuration applied? (including out-of-the-box Liferay portlets?)
I figured it out myself.
That one thing that the Fragment Editor does not tell you is that the HTML part of a fragment actually is interpreted as a Freemarker template, with the caveat that only Freemarkers alternative syntax is allowed.
That, in turn, means that Liferays taglibs are available, which means we can use the tag <liferay-portlet:runtime> (ported to freemarker alternative syntax, of course), which does accept a defaultPreferences attribute. Now we can just configure the portlet once, find its portletPreferences XML data in the DB (see table PortletPreferences), remove values we do not want to preconfigure and then just use the resulting preferences XML as a value for the defaultPreferences attribute of the <liferay-portlet:runtime> tag.
Care has to be taken for any IDs (e.g. if you want to preconfigure an AssetCategory filter). Better fetch the corresponding object from the corresponding service and get the ID from that object.
This example provides the HTML part for a page fragment that places an AssetPublisher onto the page, preconfigured to show 12 items (instead of the default 20). (CSS, JS and Configuration of the fragment is the default as given by the Page Fragment editor.)
<div class="fragment-12345">
[#assign assetPublisherPortletPreferences="<portlet-preferences>
<preference>
<name>delta</name>
<value>12</value>
</preference>
</portlet-preferences>" /]
[#liferay_portlet["runtime"]
instanceId="${fragmentEntryLinkNamespace}assets"
portletName="com_liferay_asset_publisher_web_portlet_AssetPublisherPortlet"
defaultPreferences="${assetPublisherPortletPreferences}"
/]
</div>
Thank you for this, #orithena. You saved me a lot of trouble.
Another option, to achieve the same result but with simpler syntax, is to use the built-in freeMarkerPortletPreferences:
[#assign assetPublisherPortletPreferences=freeMarkerPortletPreferences.getPreferences({
"delta": "12",
} /]
new to drupal.
I have created a view called "my_view_2".
Inside my twig templates I use {{ my_view_2}} to render that view but nothing appears on the page.
If I declare the display of the view as page and assign a node to the view, then the view is rendered. But this way the node template is lost.
The above happens only to some views not very view I have and I can not find the differences between those that working and those that does not working.
any help is appreciated.
Looks like you want to create a view with some kind of display then use twig template to style it. If that's the case, then decide which twig template you want override and copy it over to your /theme folder.
Locate the template you wish to override.
Copy the template file from its base location into your theme folder.
(optionally) Rename the template according to the naming conventions in order to target a more specific subset of areas where the template is used.
Modify the template as you want.
With respect to views look at the below location for which template to copy/override :
core/themes/stable/templates/views/views-view.html.twig).
For example, if we want to override "views-view.html.twig" template for our view, the following template names are valid:
views-view--[viewid]--[view-display-id].html.twig
views-view--[viewid]--page.html.twig
views-view--block.html.twig
views-view--[viewid].html.twig
views-view.html.twig
Once you copy a template file into your theme and clear the cache, Drupal will start using your instance of the template file instead of the base version.
Reference:
Documentation:
https://www.drupal.org/docs/8/theming/twig/twig-template-naming-conventions
https://www.drupal.org/docs/8/theming/twig/working-with-twig-templates
I am using the latest NuGet version of orchard core. As I want to use Bulma as CSS Framework, I Need to create tepmlates. One of several Problems that I have is: How can I Access the field contents from within a liquid template.
For instance the Blog theme has the content type Article. Within Article there is a field Subtitle. I created the template Article-TextField as
<h2 class="subtitle">{{ Model.Field.Text }}</h2>
The similar .cshtml template works, but apparently with a liquid template, there is no way to Access the TextField Text property. How can I do it the right way?
The problem is that the OrchardCore.ContentFields module doesn't register the TextField type with the Liquid's TemplateContext.GlobalMemberAccessStrategy service, which prevents you from accessing any members on the TextField object.
The module does register DisplayTextFieldViewModel like so:
TemplateContext.GlobalMemberAccessStrategy.Register<DisplayTextFieldViewModel>();
Not only is this unnecessary because the LiquidViewTemplate already registers the model automatically, it also doesn't help you much, since you can only access the model's Field property, but not its Text property.
For example, this will yield some output:
{{ Model }}
This will too:
{{ Model.Field }}
But as you correctly noticed, this won't:
{{ Model.Field.Text }}
This is clearly an omission in Orchard Core, specifically in the ContentFields module.
Since you're using the NuGet packages, you can't hack it into the source code obviously. But what you could do is add a Startup class to your theme that derives from StartupBase and add the following static constructor:
static Startup()
{
TemplateContext.GlobalMemberAccessStrategy.Register<TextField>();
}
Make sure to reference the OrchardCore.ContentFields NuGet package and import the OrchardCore.ContentFields.Fields namespace for your theme to compile.
After that, you will be able to access the Text property from your Liquid template.
Finally, I would recommend that you file an issue on GitHub about this omission so that you can ultimately remove the code I mentioned from your theme's Startup file.
I'm using a freemarker template to display web contents listed in an asset publisher.
In the template I'm trying to assign the portlet-namespace in order to use some asset features (like printing the entry) like this
<#attempt>
<#assign namespace = request["portlet-namespace"]>
<#recover>
<#assign namespace = 'undefined'>
</#attempt>
So, the print button is holding te code below
<a href="javascript:${namespace}printPage_0();" title='Print'>
printPage is the method used in liferay asset publisher code in asset_print.jspf
Well, everything is working fine: when inspecting the page in a browser, I verified that the namespace has been calculated and assigned to namespace variable as well (and no error displayed in UI). However, liferay portal logs the following each time a user tries to see the whole web content (ie. clicks on read more) from the asset publisher
Expression request["portlet-namespace"] is undefined on line
Anyone has seen this problem ? Is there another way to get the portlet-namespace in a freemarker template ?
#attempt/#recover is not for recovering from normal situations, and by default it logs the error when it recovers (so that the operators will be alerted). You should instead use the exp!default operator:
<#assign namespace = request["portlet-namespace"]!'undefined'>
(Though I'm not sure why printing undefinedprintPage_0(); makes sense, but that's a different issue.)
I am using Liferay 7 as my content management system and freemarker as my template language.
How to get a small image url and also custom fields of my journal article?
I want to use those values in my ADT to render the articles in a custom way.
I got like this
First get the renderer from your current entry
<#assign renderer=curEntry.getAssetRenderer()>
Then get Journal Article from the renderer
<#assign article=renderer.getArticle()>
You can get all the custom fields from article variable
eg: for small image url
${article.getSmallImageURL()}