Thursday, 18 September 2014

Custom AUI Validation in Liferay 6.1


Implementing a custom rule for non-alphabets using AUI Validator:
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet"%>
<%@ taglib uri="http://alloy.liferay.com/tld/aui" prefix="aui"%>
<aui:form action="/abc" method="post" name="form">
<aui:input name="textitemname" label="Text Item Name" class="aui-field-required" value="" size="40">
</aui:input>
<br/><br/><aui:button cssClass="save" value="Save" type="submit"></aui:button>
</aui:form>
<script type="text/javascript" charset="utf-8">
AUI().ready('aui-form-validator', 'aui-overlay-context-panel', function(A) {
A.mix(
YUI.AUI.defaults.FormValidator.RULES,
{
alphaRule: function(val, fieldNode, ruleValue) {
if(val != ""){
var arr = val.match(/^[a-zA-Z0-9_]*$/);
if(arr == null){
return false;
}else{
return true;
}
}
return true;
}
},
true
);
var validator2 = new A.FormValidator({
boundingBox: document.<portlet:namespace/>form,
rules: {
<portlet:namespace />textitemname:{
required: true,
alphaRule:true
}
},
fieldStrings: {
<portlet:namespace />textitemname: {
required: 'TextName Required',
alphaRule: 'None other than alpha characters'
}
},
on: {
validateField: function(event) {
},
validField: function(event) {
},
errorField: function(event) {
},
submitError: function(event) {
alert("submitError");
var formEvent = event.validator.formEvent;
var errors = event.validator.errors;
},
submit: function(event) {
alert("Submit");
var formEvent = event.validator.formEvent;
return false;
}
}
});
});
</script>

A simple program to compare Start Date and End Date using AUI Validator:

<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet"%>
<%@ taglib uri="http://alloy.liferay.com/tld/aui" prefix="aui"%>
<aui:form action="/abc" method="post" name="form">
<div class="aui-field-content" id="datePicker">
<table>
<tr>
<td><aui:input label="Start Date" name="startDate" size="20">
<aui:validator name="required" errorMessage="Start Date is required. Select a value." />
</aui:input>
</td>
<td valign="top" style="padding-top: 18px">
<div class="aui-datepicker-button-wrapper">
<button class="aui-buttonitem-content aui-widget aui-component aui-buttonitem aui-state-default aui-buttonitem-icon-only"
id="startDate" type="button">
<span class="aui-buttonitem-icon aui-icon aui-icon-calendar"></span>
</button>
</td>
</div>
</tr>
</table>
</div>
<div class="aui-field-content" id="datePicker1">
<table>
<tr>
<td><aui:input label="End Date" name="endDate" size="20">
<aui:validator name="required" errorMessage="End Date is required. Select a value."/>
<aui:validator name="custom"
errorMessage="Leave blank or enter a date greater than the begin date.">
function(val, fieldNode, ruleValue)
{
var startDateObj = document.getElementById("<portlet:namespace />startDate");
var startDate;
var result=false;
//case when end date is blank
//no validation required then
if(val == ""){
return true;
}
if(startDateObj) {
startDate = new Date(startDateObj.value);
}else{
result = false;
}
var endDate = new Date(val);
if(startDate && endDate){
result = endDate.getTime()>startDate.getTime();
}else{
result = false;
}
return result;
}
</aui:validator>
</aui:input>
</td>
<td valign="top" style="padding-top: 18px">
<div class="aui-datepicker-button-wrapper">
<button class="aui-buttonitem-content aui-widget aui-component aui-buttonitem aui-state-default aui-buttonitem-icon-only" id="endDate" type="button">
<span class="aui-buttonitem-icon aui-icon aui-icon-calendar"></span>
</button>
</td>
</div>
</tr>
</table>
</div>
<br/><br/><aui:button cssClass="save" value="Save" type="Submit"></aui:button>
</aui:form>
<script type="text/javascript" charset="utf-8">
AUI().ready('alloy-node','aui-form-validator', 'aui-overlay-context-panel', 'aui-datepicker', function(A) {
var startDate = new A.DatePicker({
trigger: '#<portlet:namespace />startDate',
calendar: {
dateFormat: '%m/%d/%Y',
},
yearRange: [1990, (new Date).getFullYear()]
}).render('#datePicker');
A.one("#startDate").on("click", function () {
startDate.show();
});
var endDate = new A.DatePicker({
trigger: '#<portlet:namespace />endDate',
calendar: {
dateFormat: '%m/%d/%Y',
},
yearRange: [1990, (new Date).getFullYear()]
}).render('#datePicker1');
A.one("#endDate").on("click", function () {
endDate.show();
});
});
</script>
Many a times it is required, that we want to provide rules to dynamically added fields.
We can use current validator and iterate over rules by passing rowId:

var rules = validator2.get('rules'); // get current validator
rules['<portlet:namespace />info' + dynamicRowId] = {required: true};
rules['<portlet:namespace />desc' + dynamicRowId] = {required: true, maxLength: 255};

Tuesday, 2 September 2014

Flickr Integration with Liferay


Many a times, we work with clients who like to maintain their account using several Social Media Tools. We might require to display them in the form of feeds by pulling data from one of their accounts.

I have taken an example of Flickr here. We can create a Liferay portlet and show public contents by configuring flickr feed id and number of feeds on web page.



Create a  Liferay portlet eg. FlickrApp Portlet. 

In liferay-portlet.xml specify your configurationAction class let say FlickrConfigurationActionImpl.

In FlickrConfigurationActionImpl, you need to add code for storing preferences. 
Below is sample code:
package com.test.flickr.portlet.controller;
import java.io.IOException;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletConfig;
import javax.portlet.PortletPreferences;
import javax.portlet.ReadOnlyException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.ValidatorException;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.portlet.ConfigurationAction;
import com.liferay.portal.kernel.servlet.SessionErrors;
import com.liferay.portal.kernel.servlet.SessionMessages;
import com.liferay.portal.kernel.util.Constants;
import com.liferay.portal.kernel.util.ParamUtil;
import com.liferay.portlet.PortletPreferencesFactoryUtil;
public class FlickrConfigurationActionImpl implements ConfigurationAction {
private static Log log = LogFactoryUtil.getLog(FlickrConfigurationActionImpl.class);
public String render(PortletConfig portletConfig,
RenderRequest renderRequest, RenderResponse renderResponse)
throws IOException,PortalException {
return "/html/configuration.jsp";
}
public void processAction(PortletConfig portletConfig,
ActionRequest actionRequest, ActionResponse actionResponse)
{
String portletResource = ParamUtil.getString(actionRequest, "portletResource");
PortletPreferences preferences = null;
try {
try {
preferences = PortletPreferencesFactoryUtil.getPortletSetup(actionRequest, portletResource);
} catch (PortalException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String flickrFeed = ParamUtil.getString(actionRequest, "flickrFeed");
String numberFeed = ParamUtil.getString(actionRequest, "numberFeed");
String cmd = ParamUtil.getString(actionRequest, Constants.CMD);
if(cmd.equalsIgnoreCase(Constants.UPDATE)){
preferences.setValue("flickrFeed", flickrFeed);
preferences.setValue("numberFeed", numberFeed);
if (SessionErrors.isEmpty(actionRequest)) {
preferences.store();
SessionMessages.add(actionRequest, "success");
}
}
} catch (SystemException e) {
log.info("System exception");
}catch (IOException e) {
log.info("Io exception");
}
catch (ReadOnlyException e) {
log.info("Error while setting value in preferences");
}
catch (ValidatorException e) {
log.info("Error in storing value in preferences");
}
}
}
In configuration.jsp, you need to write logic for providing preferences i.e. showing inputs for feeds.
<%
PortletPreferences preferences = renderRequest.getPreferences();
String portletResource = ParamUtil.getString(request, "portletResource");
if (Validator.isNotNull(portletResource)) {
preferences = PortletPreferencesFactoryUtil.getPortletSetup(request, portletResource);
}
String flickrFeed = preferences.getValue("flickrFeed","12037949754@N01"); // default Id in Feed
String numberFeed = preferences.getValue("numberFeed","3");
%>
<liferay-ui:success key="success" message="Successfully saved" />
<liferay-portlet:actionURL portletConfiguration="true" var="configurationActionURL" />
<form action="<%= configurationActionURL %>" method="post" name="fm">
<input name="<%= Constants.CMD %>" type="hidden" value="<%= Constants.UPDATE %>" />
<fieldset class="block-labels">
<legend><liferay-ui:message key="Configuration for Flickr" /></legend>
<aui:input label="Flickr Feed Id" name="flickrFeed" type="text" value="<%= flickrFeed %>" />
<aui:input label="No of Feed" name="numberFeed" type="text" value="<%= numberFeed %>" />
</fieldset>
<br/>
<input name="submit" type="submit" value="Save" />
</form>


In view.jsp, you need to add logic for storing preferences:
<%
String ctxPath = request.getContextPath();
if (ctxPath != null && ctxPath.length() == 1)
{
ctxPath = "";
}
PortletPreferences preferences = renderRequest.getPreferences();
String portletResource = ParamUtil.getString(request, "portletResource");
if (Validator.isNotNull(portletResource)) {
preferences = PortletPreferencesFactoryUtil.getPortletSetup(request, portletResource);
}
String flickrFeed = preferences.getValue("flickrFeed", StringPool.BLANK);
String numberFeed = preferences.getValue("numberFeed", StringPool.BLANK);
if(flickrFeed.equals(null)|| flickrFeed == "" ){ flickrFeed = "64933450@N05"; }
if(numberFeed.equals(null)|| numberFeed == "" ){ numberFeed = "3"; }
%>
<div class="seperator"></div>
<input id="flickrSearch" value="<%= flickrFeed %>" type="hidden">
<input id="flickrFeedList" value="<%= numberFeed %>" type="hidden">
<div class="sidebar_widget">
<h3 class="widget_head"><img alt="img" title="Photos from Flickr" src="<%=ctxPath%>/images/flickr_icon.png">Photos from Flickr</h3>
<div class="widget_content">
<ul id="flickrId">
</ul>
</div>
<div class="widget_footer">
<a href="http://www.flickr.com/photos/<%=flickrFeed %>">More Photos on Flickr</a>
</div>
</div>
view raw flickrview.jsp hosted with ❤ by GitHub


You need to add the FlickrFeedAPI for accessing these feeds.
1. Download latest Jquery min js file
2. Download Flickr feed js file from Jquery Feed Plugin
3. Create a flickr-setup.js file which takes feed count and feed id as input and displays feeds as shown below:
$(document).ready(function(){
$('#flickrId').flickr({
limit: $("#flickrFeedList").val(),
qstrings: {
id: $("#flickrSearch").val() // flickr - ID
},
itemTemplate: '<li>'+'<img alt="img" src="{{image_s}}"><br/><a href="{{link}}"> {{title}} </a><div><small>Uploaded on {{date_uploaded}} <br> </small><br/></div>'+'</li>'
});
});
view raw flickrSetup.js hosted with ❤ by GitHub

For FlickrServices, you can refer : Feeds

Thanks for reading! Happy Learning !