Monday, August 25, 2014

Character counter in AlloyUI Liferay

In liferay, we basically use jQuery to display counter which limits the amount of text field.

But this is a out-of-box module provided by AlloyUI which does the same.

How to Use?

First, we need to create text field and span which shows max length count number.

 <input type="text" id="input"/>  
 <span id="counter"></span> character(s) remaining  

Second, we need to bind input element id and span element id for setting the maximum length.

 AUI().ready(  
  'aui-char-counter',  
  function(A) {  
   new A.CharCounter(  
    {  
     counter: '#counter',  
     input: '#input',  
     maxLength: 10  
    }  
   );  
  }  
 );  

That's it and we're done.



Friday, August 22, 2014

Fetch list of file entries of any folder in Liferay Document and Media

We need a list of documents (their titles shown) and those titles to link to the documents for downloading.

Refer below code,

 Long parentFolderId = DLFolderConstants.DEFAULT_PARENT_FOLDER_ID;  
 DLFolder folder = DLFolderLocalServiceUtil.getFolder(groupId, parentFolderId, dirName);  
 ThemeDisplay themeDisplay = (ThemeDisplay) renderRequest.getAttribute(WebKeys.THEME_DISPLAY);  
  List<DLFileEntry> fileEntryService = null;  
  try {  
       fileEntryService = DLFileEntryLocalServiceUtil.getFileEntries(themeDisplay.getScopeGroupId(),folder.getFolderId(),-1, -1, null); //12345 is folderId  
  } catch (SystemException e) {  
       e.printStackTrace();  
  }  
 for(DLFileEntry fileEntryObj : fileEntryService){  
      System.out.println(fileEntryObj.getTitle());   
 }  

We can use below code in velocity template,

 #set($service = $serviceLocator.findService("com.liferay.portlet.documentlibrary.service.DLFileEntryLocalService"))  
 #set($gid = $getterUtil.getLong($request.get("theme-display").get("scope-group-id")))  
 #set($fid = $getterUtil.getLong($folderId.getData()))  
 #set($files = $service.getFileEntries($gid, $fid))  
 #foreach($doc in $files)  
   #set($uet = $httpUtil.encodeURL($htmlUtil.unescape($doc.getTitle())))  
   <a href="/documents/$gid/$fid/$uet">$doc.getTitle()</a><br />  
 #end  


Liferay 6.2 changes - Portlet namespace in Spring MVC

In Liferay 6.2 version when we submit any form data it returns always "no-param", which means, the actionRequest.getParameter() return null.

Also, at the time of migrating annotation based spring portlet from 6.1 to 6.2.10 then we can receive null parameter with actionURL at controller side. [JSP > FORM > SUBMIT ACTION URL  > CONTROLLER > ALL PARAMETERS NULL ]

How to fix this?

we need to put a namespace prefix to your name value like this:-
 <input type="text" name="<portlet:namespace />inputTextName" />  

or

we can set the requires-namespaced-parameters setting to false in your liferay-portlet.xml.
 <requires-namespaced-parameters>false</requires-namespaced-parameters>  

This is a change since Liferay 6.2:  https://github.com/liferay/liferay-aui-upgrade-tool/issues/30




Thursday, August 21, 2014

Method overloading in javascript

When we  use method overloading as below in javascipt code.

 function anyfunction()  
 {  
   //1st function  
 }  
 function anyfunction(a)  
 {  
   //2nd function  
 }  
 function anyfunction(a,b)  
 {  
   //3rd function  
 }  
 anyfunction(); // function call goes here  

Javascript does not support method overloading (as in Java or similiar), your third function overwrites the previous declarations.

Instead, it supports variable arguments via the arguments object. We can handle like this,

 function anyfunction(a, b) {  
   if (arguments.length == 0) { // a, b are undefined  
     // 1st body  
   } else if (arguments.length == 1) { // b is undefined  
     // 2nd body  
   } else if (arguments.length == 2) { // both have values  
     // 3rd body  
   } // else throw new SyntaxError?  
 }  

We also can just check for typeof a == "undefined" etc, this would allow calling anyfunction(undefined), where arguments.length is 1. This might allow easer calling with various parameters, e.g. when you have possibly-empty variables.

 function anyFunction(a, b) {  
   if (typeof a === 'undefined') {  
     // Do the 0-parameter logic  
   } else if (typeof b === 'undefined') {  
     // Do the 1-parameter logic  
   } else {  
     // Do the 2-parameter logic  
   }  
 }  


Asset category in custom portlet in Liferay

Whenever one of your custom content is created you need to let the asset framework know. Don't worry, it is simple. You just need to invoke a method of the asset framework. When invoking this method you will also let the framework know about the tags and/or categories of the content that was just authored.

This is the code you can put it to any jsp page for implementing category popup.

// vManag is the object which is refering to custom portlet named VideoManagement.

In JSP

  <tr><td><b>Categories</b></td>  
 <%  
 String categoryId = null,categoryIds = "";  
 if(Validator.isNotNull(vManag)) {
 if(Validator.isNull(vManag.getCategoryIds())){  
   categoryId = null; // while adding record  
 }else{  
   categoryId = vManag.getCategoryIds(); // get all catgs for that record  
 }  
 if(Validator.isNotNull(categoryId)){  
   String id[] = categoryId.split(",");  
   for(int i=0;i<id.length;i++)  
   {  
    if(String.valueOf(id[i]).equals("") || String.valueOf(id[i]).equals(null)){  
     //return;  
    }else{  
       List<AssetCategory> assetCategory = AssetCategoryLocalServiceUtil.getCategories();  
   for(AssetCategory aCat : assetCategory){  
     if(id[i].equals(String.valueOf(aCat.getCategoryId()))){  
       AssetCategory asset  =(AssetCategory) AssetCategoryLocalServiceUtil .getCategory(aCat.getCategoryId());  
   if(Validator.isNotNull(asset.getCategoryId())){  
      categoryIds= categoryIds.concat(String.valueOf(asset.getCategoryId()));  
     if(i<id.length-1)  
      categoryIds= categoryIds.concat(",");   
      // append categoryId with comma except last  
     }  
    }  
   }  
  }  
  }  
 }  
 } %>  

 <td><liferay-ui:asset-categories-selector curCategoryIds='<%= Validator.isNull(vManag) ? "" : categoryIds %>'/></td></tr>  


The tag <liferay-ui:asset-categories-selector> uses AssetCategoryServiceUtil.getCategories(className, classPK) to get the list of categories and populates the curCategoryIds from this list.

All the methods that you will need to invoke are part of the AssetEntryLocalService. In particular you should access these methods using either the static methods of AssetLocalServiceUtil or by using an instance of the AssetEntryLocalService injected by Spring.

First time you are adding record in custom table so you have to select cateogry from popup.It will show all categories in the category popup by specifying empty string in curCategoryIds and At the time of editing record you have to get categoryIds [like 64664,64613] from custom table that is already stored after adding record and then assign categoryIds to curCategoryIds in asset-categories-selector tag.

So you can see the category selected and if 'select' button is clicked, the same category is shown as checked and that will be useful when you editing any record of custom-table to show default selected values in that popup.

When user select any category from that popup. It will automatically create a hidden field with name assetCategoryIds in the same page.

 <input type="hidden" value="64664,64613" name="_videosmanagement_WAR_videosmanagementportlet_assetCategoryIds" id="_videosmanagement_WAR_videosmanagementportlet_assetCategoryIds" class="aui-field-input aui-field-input-hidden">  

In Java class

So here you can get the values of selected categoryIds like 64664,64613[two category selected in popup]

you can make entry in custom table for adding/editing record and also in assetEntry table for that same recordId.

This is the logic for making entry in assetEntry table for that recordId.

 com.liferay.portal.service.ServiceContext serviceContext = null;  
 String categoryIds = ParamUtil.getString(actionRequest,"assetCategoryIds");  
 try {  
 serviceContext = ServiceContextFactory.getInstance( VideoManagement.class.getName(), actionRequest);  
 } catch (PortalException e) {  
 e.printStackTrace();  
 } catch (SystemException e) {  
 e.printStackTrace();  
 }  
 AssetEntry assetEntry = null;  
 try {  
 assetEntry = AssetEntryLocalServiceUtil.updateEntry(  
 userId,  
 groupId,  
 VideoManagement.class.getName(),  
 vManag.getVideoId(),  
 serviceContext.getUuid(),  
 "".equals(StringUtil.trim(categoryIds)) ? null: categoryIds, null, true, new Date(),null, release_date, null, "text/html", video_title,description, summary, url, 0, 0, null, false);  
 } catch (Exception e) {  
 LOGGER.debug("Error while Converting StringArray to LongArray ! :"  
 + e.getMessage());  
 // e.printStackTrace();  
 }  

userId :- is the identifier of the user who created the content.

VideoManagement.class.getName() :- which is the class name refering to custom portlet named VideoManagement.

vManag.getVideoId() :- represent as classPK which is unique recordId for that content[specify Id of that record which is already added/updated].

assetCategoryIds :- represent the categories that have been selected by the author of the content.

Url :- which specify the url of content i.e for videomanagement portlet you can specify videoURL.

Hope this would be helpful for those who need to develop asset category functionality in custom portlet

Refer more,
https://www.liferay.com/documentation/liferay-portal/6.1/development/-/ai/asset-framewo-4

Liferay input move boxes

This is very good feature of liferay. This is useful when user can use input move box having left and right boxes where user can move fields from one box to other.

How to use?

In Jsp

We need to make keyvalue pair to be passed inside leftBox and rightBox
<% 
           List leftBox = new ArrayList(), rightBox = new ArrayList(); 
           leftBox.add(new KeyValuePair("key", "value"));
%>

Below liferay tag which is useful to make input move box
 <form action="<%= actionURL1 %>" method="post" name="<portlet:namespace />fm" >  
 <liferay-ui:input-move-boxes rightList="<%=rightBox%>" rightTitle="Visible Columns" leftBoxName="allFieldsList" leftList="<%=leftBox%>" rightBoxName="displayFieldsList" leftTitle="All Columns" leftReorder="false" rightReorder="true" cssClass="custom-move-boxes" />   
 <input name="<portlet:namespace />hiddenLeftFields" id="<portlet:namespace />hiddenLeftFields" type="hidden" />   
 <input name="<portlet:namespace />hiddenRightFields" id="<portlet:namespace />hiddenRightFields" type="hidden" />   
 <a href="#" onclick="<portlet:namespace />submitForm();" class="save">Save</a>   
 </form>  

AlloyUI Script which is used for storing selected values in hidden input fields
 <aui:script>  
 Liferay.provide(  
 window,  
 '<portlet:namespace />submitForm',  
 function() {  
 document.<portlet:namespace/>fm.<portlet:namespace />hiddenLeftFields.value = Liferay.Util.listSelect(document.<portlet:namespace/>fm.<portlet:namespace />allFieldsList);  
 document.<portlet:namespace/>fm.<portlet:namespace />hiddenRightFields.value = Liferay.Util.listSelect(document.<portlet:namespace/>fm.<portlet:namespace />displayFieldsList);  
 document.<portlet:namespace/>fm.submit();  
 }, ['liferay-util-list-fields']  
 );  
 </aui:script>  

In Java Class

We can fetch all selected fields separated by comma
 String hideFields = ParamUtil.getString(actionRequest,"hiddenLeftFields");  
 String displayFields = ParamUtil.getString(actionRequest, "hiddenRightFields");  


Wednesday, August 20, 2014

Liferay auto fields

This is a very good feature in liferay and it is available out-of-box in liferay.

We have created html fields and we need to repeat multiple times in the form, we can use the alloyui module that is liferay-auto-fields.

How to use?

Inside Jsp


Note:- Here, you have to use alloyUI form to support this feature.

 <div id="fields">  
 <div class="lfr-form-row lfr-form-row-inline">  
  <div class="row-fields">  
  /* Html Form Fields like Number, Extension, Type etc. */  
  <aui:input id="number0" name="number0" label="Number"></aui:input>  
  </div>  
 <div>  
 </div>  

Here, whatever fields we add in row-fields div that will be repeated multiple time on click.

AlloyUI Script

 <aui:script use="liferay-auto-fields">  
   new Liferay.AutoFields({  
    contentBox: '#fields',  
    fieldIndexes: '<portlet:namespace />fieldIndexes'  
    }  
   ).render();  
 </aui:script>  

Here,
contentBox -  main div on which it will be applied
fieldIndexes - name of variable that we need to use in java class for getting all selected field values by index

In Action class 

 public void getFieldsData(ActionRequest actionRequest,ActionResponse response)  
                   throws Exception {  
  String fieldIndexes= actionRequest.getParameter("fieldIndexes");  
  int[] fieldIndexesArray = StringUtil.split(fieldIndexes, 0);//we will get indexes of selected multiple fields  
     for (int fieldIndex : fieldIndexesArray) {  
        String number = ParamUtil.getString(actionRequest, "number" + fieldIndex);  
        //we can get values by specifying name of field and fieldIndex                      
     }  
 }  




Popular Posts