Jun 13, 2013

IPC using client side java script


  • Introduction

    The client-side mechanism to communicate portlets is based on events,uses events instead of direct js calls accross portlets is very important
    since it's not possible to know at deployment time which other portlets will be available in a given page.

    By firing/triggering an event one portlet just notifies that something has happened,
    and then one or more of the other portlets in the page might be listening and act accordingly.

    Code snippet:

    Example: Updating a label inside second-portlet using a link provided in the first-portlet.

    snippet-1: insert the below code in to docroot/view.jsp of first-portlet.

    <script>
    jQuery(
            function () {
              jQuery('a.change_label').click(
                function(event) {
                  Liferay.fire('changeLabel');
                  return false;
                });
              jQuery('a.remove_label').click(
                function(event) {
                  Liferay.fire('removeLabel');
                  return false;
                });
           }
    );
    </script>
    <a class="change_label">Click here to fire event</a><br/>
    <a class="remove_label">Remove label on second portlet</a>


    snippet-2: insert the below code in to docroot/view.jsp of second-portlet.

    <script>
            Liferay.on(
               'changeLabel',
               function(event) {
                 jQuery('label.info_label').html('Event fired on first-portlet');
               }
            );
            Liferay.on(
               'removeLabel',
               function(event) {
                 jQuery('label.info_label').html('');
               }
            );
                  
    </script>
    <br/><label class="info_label" />

    Deploy these portlets and check how they work.

    Congratulations !!

    NOTE:

     Liferay.trigger(eventName, data)
     Liferay.bind(eventName, function, [scope])
    These methods have been deprecated in Liferay 6 in favor of
     Liferay.fire(eventName, data)
     Liferay.on(eventName, function, [scope])

     For more Information about this please check this link

     

     

May 28, 2013

AUI Carousel using WebContent (Structure/Template)


To Create carousel like above image or as shown on Liferay home page
Follow under Given Steps
  • Create Structure using under given structure.xml code
  • Create Template using under given template.vm code
  • After creating structure and template now just add appropriate parameters and images.
  • And your carousel is ready for you.

There is a nice tutorial on AlloyUI Carousel which describes in detail about it in very simple term.

structure.xml

1234567891011121314151617181920212223242526272829303132333435363738394041424344


<root>
 <dynamic-element name="imageIndex" type="text" index-type="" repeatable="false">
  <meta-data>
   <entry name="displayAsTooltip"><![CDATA[true]]></entry>
   <entry name="required"><![CDATA[false]]></entry>
   <entry name="instructions"><![CDATA[Index of the first visible item of the carousel]]></entry>
   <entry name="label"><![CDATA[Image Index]]></entry>
   <entry name="predefinedValue"><![CDATA[0]]></entry>
  </meta-data>
 </dynamic-element>
 <dynamic-element name="timeInterval" type="text" index-type="" repeatable="false">
  <meta-data>
   <entry name="displayAsTooltip"><![CDATA[true]]></entry>
   <entry name="required"><![CDATA[false]]></entry>
   <entry name="instructions"><![CDATA[Interval time in seconds between an item transition.]]></entry>
   <entry name="label"><![CDATA[Time Interval]]></entry>
   <entry name="predefinedValue"><![CDATA[0.75]]></entry>
  </meta-data>
 </dynamic-element>
 <dynamic-element name="maxImageHeight" type="text" index-type="" repeatable="false">
  <meta-data>
   <entry name="displayAsTooltip"><![CDATA[true]]></entry>
   <entry name="required"><![CDATA[false]]></entry>
   <entry name="instructions"><![CDATA[Provide max height of image element. ex-200]]></entry>
   <entry name="label"><![CDATA[Max Image Height]]></entry>
   <entry name="predefinedValue"><![CDATA[250]]></entry>
  </meta-data>
 </dynamic-element>
 <dynamic-element name="maxImageWidth" type="text" index-type="" repeatable="false">
  <meta-data>
   <entry name="displayAsTooltip"><![CDATA[true]]></entry>
   <entry name="required"><![CDATA[false]]></entry>
   <entry name="instructions"><![CDATA[Provide max width of image element. ex-150]]></entry>
   <entry name="label"><![CDATA[Max Image Width]]></entry>
   <entry name="predefinedValue"><![CDATA[600]]></entry>
  </meta-data>
 </dynamic-element>
 <dynamic-element name="ImageElementSet" type="selection_break" index-type="keyword" repeatable="true">
  <dynamic-element name="image" type="image" index-type="keyword" repeatable="false" />
  <dynamic-element name="linkUrl" type="text" index-type="keyword" repeatable="false"/>
 </dynamic-element>
</root>
Below are the details of some basic parameters that we've defined in structure.xml
  • imageIndex - Index of the first visible item of the carousel
  • timeInterval - Interval time in seconds between an item transition
  • maxImageHeight - Provide max height of image element. ex-200
  • maxImageWidth - Provide max width of image element. ex-150
  • ImageElementSet
    • image - Browse & upload image to be displayed
    • linkUrl - Url of image if you want to make it clickable
     

template.vm

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
#set($imageWidth = $maxImageWidth.Data)
#set($imageHeight = $maxImageHeight.Data)
#set($imageWidthPx = $imageWidth + "px")
#set($imageHeightPx = $imageHeight + "px")
#set($interval = $timeInterval.Data)
#set($activeIndexValue = $imageIndex.Data)
 
<style type="text/css">
        .aui-carousel {
  -moz-user-select: none;
  margin: 20px 0;
 }
 .aui-carousel-item {
  border-radius: 10px 10px 10px 10px;
  text-indent: -9999em;
 }
 .aui-carousel li {
  margin: 0 !important;
 }
</style>
 
#set($totalCount = 0)
<div id="carousal">
 #foreach($imageElement in $ImageElementSet.getSiblings())
  #if($imageElement.image.getData() != "")
   #if($imageElement.linkUrl.getData() != "")
    <a href="$imageElement.linkUrl.Data">
     <img class="aui-carousel-item" src="$imageElement.image.Data" height="$imageHeightPx" width="$imageWidthPx" />
    </a>
   #else
    <img class="aui-carousel-item" src="$imageElement.image.Data" height="$imageHeightPx" width="$imageWidthPx" />
   #end
   #set($totalCount = $totalCount + 1)
  #end
 #end
</div>
 
#if($totalCount > 0)
 <script>
  AUI().ready('aui-carousel', function(A) 
  { 
   var carousel = new A.Carousel(
   { 
    contentBox: '#carousal', 
    activeIndex: $activeIndexValue,
    intervalTime: $interval, 
    width: $imageWidth, 
    height: $imageHeight 
   }).render(); 
  });
 </script>
#end

May 8, 2013

Liferay auto complete field example




  • Create field for auto complete

          <div id="autoCompleteDiv">
               <aui:input type="text" name="xyz" id="txtAutoComplete" label="Auto Complete Field" />
          </div>

         NOTE :- You can use <span> also insted of <div>

  • Create Resource URL

         <portlet:resourceURL var="autoCompleteName" id="resourceId" />


  • Write AUI script for auto complete field

         <aui:script use="aui-autocomplete, autocomplete-filters, autocomplete-highlighters">
                  var dataSource = new A.DataSource.IO(
                  {
                        source: '<%=autoCompletName.toString()%>'
                  });
                  var autocomplete = new A.AutoComplete(
                  {
                             dataSource: dataSource,
                             matchKey: 'name',
                             schema: {
                             resultListLocator: 'response',
                             resultFields: ['key', 'name']
                  },
                    schemaType:'json',
                    contentBox: '#autoCompleteDiv',
                    input:'#<portlet:namespace />txtAutoComplete',
                    typeAhead: false
                   });
                autocomplete.generateRequest = function(query) {
                         return {
                             request: '&keywords=' + query
                         };
                 }
                 autocomplete.render();
                });
         </aui:script>

  • Write Resource method that serve to resource URL

          @ResourceMapping("resourceId")
   public void serveResource(ResourceRequest request, ResourceResponse response)
          {
               JSONObject json = JSONFactoryUtil.createJSONObject();
              JSONArray results = JSONFactoryUtil.createJSONArray();

             String keyword = ParamUtil.getString(resourceRequest, DisplayTerms.KEYWORDS);

             List filteredEntries = getFilteredEntries(keyword);

            for (Object entries : filteredEntries)
            {
               Object[] entry = (Object[]) entries;

               JSONObject listEntry = JSONFactoryUtil.createJSONObject();

              listEntry.put("key", Long.parseLong("" + entry[0]));
              listEntry.put("name", "" + entry[1]);

              results.put(listEntry);
          }
           json.put("response", results);
           PrintWriter writer = resourceResponse.getWriter();
           writer.print(json.toString());

        }

        private static List getFilteredEntries(String query) throws SystemException
       {
            List entries = null;
            DynamicQuery xzyQuery = DynamicQueryFactoryUtil.forClass(Xyz.class);
            if (Validator.isNotNull(query))
           {
             xzyQuery.add(RestrictionsFactoryUtil.ilike("title", "%" + query + "%"));    
         
             ProjectionList projectionList = ProjectionFactoryUtil.projectionList();
             projectionList.add(ProjectionFactoryUtil.property("xyzId"));
             projectionList.add(ProjectionFactoryUtil.property("title"));
             xzyQuery.setProjection(projectionList);

              entries = XyzLocalServiceUtil.dynamicQuery(xzyQuery);
            }
           return entries;
        }

NOTE :- Here I used "@ResourceMapping("resourceId")" because I used Spring, make appropriate changes as per your requirement to call the " serveResource(...)" method.

May 7, 2013

Liferay Custom Query

 Step by step process of "How to use custom query"

There are four steps to create custom query and use it.
NOTE :- Here I assume that you know about liferay service builder.

step 1:- custom-sql folder


  • Create custom-sql folder in docroot/WEB-INF/src package
  • Add new default.xml file in above created folder.
  • The content of default.xml is as under
                <?xml version="1.0" encoding="UTF-8"?>
               <custom-sql>
                  <sql file="custom-sql/query.xml" />
                  <sql file="custom-sql/anotherquery.xml" />
              </custom-sql>
  • You can add multiple sql file in above content.
  • Now create query.xml in same folder
  • Write your sql-query in query.xml as under.
               <?xml version="1.0" encoding="UTF-8"?>
               <custom-sql>
                    <sql id="com.test.services.xyz.service.persistence.uniqueId">


  <![CDATA[
select * from xyz x where x.userId=? AND x.name=?;
  ]]>
  </sql>
           </custom-sql > 
  • The sql id is unique so use the package name of service persistence class and then (xyz) uniqueId.
    • Like "com.test.services.xyz.service.persistence.uniqueId"
    • Here "com.test.services.xyz.service.persistence" is package path of "xyz" service.
    • "Xyz" is the entity name.
    • Here "xyz" is the service created for means table name which we created using service builder.

step 2:- creating service finder impl


  • Create "XyzFinderImpl.java" in "com.test.services.xyz.service.persistence" package of service.
  • NOTE:- Give the name of finder impl related to the service name
    • Here in our case the service is "XYZ" so we create "XyzFinderImpl.java"
  • The content of finder impl is as under
          package com.test.services.xyz.service.persistence;

          import com.liferay.portal.kernel.dao.orm.QueryPos;
          import com.liferay.portal.kernel.dao.orm.SQLQuery;
          import com.liferay.portal.kernel.dao.orm.Session;
          import com.liferay.portal.kernel.exception.SystemException;
          import com.liferay.portal.kernel.util.StringUtil;
          import com.liferay.portal.kernel.util.Validator;
          import com.liferay.portal.service.persistence.impl.BasePersistenceImpl;
          import com.liferay.util.dao.orm.CustomSQLUtil;

          public class XyzFinderImpl extends BasePersistenceImpl<xyz> implements XyzFinder
          {
             public static String CUSTOM_SQL = "com.test.services.xyz.service.persistence.uniqueId";
   
              public List getXYZ(Long userId, String name) throws SystemException
              {
                  Session session = null;
                  String sql = null;
                  try
                  {
                      session = openSession();
                      if (Validator.isNotNull(userId))
                      {
                          sql = CustomSQLUtil.get(CUSTOM_SQL);
                      } 
                      SQLQuery query = session.createSQLQuery(sql);
                      QueryPos qPos = QueryPos.getInstance(query);
                      qPos.add(userId);
                      qPos.add(name);

           //           query.executeUpdate();
                     return (List) query.list();
                  } catch (Exception e)
                  {
                      e.printStackTrace();
                  }
              }

          }

  • Right now "XyzFinder" interface is not available so no need to worry for that.
  • After doing this much build the service again so it's create appropriate classes and interfaces for you.

step 3:-Define method in service Impl


  • Open XyzLocalServiceImpl generated while first time you build service for that.
  • Define method that call the finder method of "XyzFinderImple.java" class as below.
                    public List getUser(Long userId, String name) throws SystemException
                   {
                      return  XyzFinderUtil.getXYZ(userId, name);
                    }
    • Now build service again and after that you are ready to use the custom query.

    step 4:- use of custom-query


    • Call the method as below in your class.
                 List users = XyzLocalServiceUtil.getUser(12345,"test");