Site icon Pro Liferay

Alloy Ajax in Liferay Portlet

Ajax

Liferay serveResource and alloy aui-io-request module made Ajax easy to implement in Liferay Portlet. If you have basic knowledge of Ajax and you want to learn how ajax call happens by Alloy A.io.request method then this article can help you to understand inside out. At the end of this article you will be able to know how A.io.request  works and what’s the role of serveResource method to implement Ajax


New to Ajax?

i) AJAX stands for Asynchronous JavaScript and XML.

ii) AJAX is not a new programming language.Its new way to use existing standards.

iii) Using AJAX we can exchange data with server and update a portion of web page without reloading the whole page. 

iv) In Portlet Application serveResource is the method which provides data like JSON, XML as response 


1.Ajax call with minimum code

<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<%@ taglib uri="http://liferay.com/tld/theme" prefix="theme" %>
<%@ taglib uri="http://liferay.com/tld/aui" prefix="aui" %>
<theme:defineObjects/>
<portlet:defineObjects />
<portlet:resourceURL var="resourceURL"/>
<script type="text/javascript">
function callServeResource(){
	AUI().use('aui-io-request', function(A){
		A.io.request('<%=resourceURL.toString()%>');
	});
}

</script>
<form name="fm" id="fm">
<input type="button" value="Click" onclick="callServeResource()">
</form>

 The above code should call the below method of your portlet 

@Override
	public void serveResource(ResourceRequest resourceRequest,
			ResourceResponse resourceResponse) throws IOException,
			PortletException {
		System.out.println("#############AJAX CALL####################");
		super.serveResource(resourceRequest, resourceResponse);
	}

Note 1: We are just creating a resource URL by <portlet:resourceURL var=”resourceURL”/>

Note 2:  A.io.request is the JavaScript alloy function which needs a URL for AJAX call.

Note 3: Print something in your serveResource method to check whether its really calling serveResource  method or not. 

2.Send some data to serveResource method by Ajax call

<portlet:resourceURL var="resourceURL"/>
<script type="text/javascript">
function callServeResource(){
	AUI().use('aui-io-request', function(A){

		A.io.request('<%=resourceURL.toString()%>', {
			   method: 'post',
			   data: {
				   site: 'www.proliferay.com',
				   author: 'Hamidul Islam'
			   }
	    });

	});
}
</script>
<form name="fm" id="fm">
<input type="button" value="Click" onclick="callServeResource()">
</form>

In the above code we are sending two parameters site and author to serveResource method. You can read these two parameters in your serveResource method as below 

@Override
	public void serveResource(ResourceRequest resourceRequest,
			ResourceResponse resourceResponse) throws IOException,
			PortletException {

		/**
		 * Read data sent by AJAX
		 */

		String site = ParamUtil.getString(resourceRequest, "site");
		String author = ParamUtil.getString(resourceRequest, "author");

		System.out.println("The value of site parameter sent by AJAX  "+site);
		System.out.println("The value of author parameter sent by AJAX  "+author);
		super.serveResource(resourceRequest, resourceResponse);
	}

Problem:

You might be thinking that you can read the posted data or parameters in your serveResource  method without any problem. But serveResource method will ignore any parameters without namespace. Therefore you get nothing in your serveResource method. There are two solutions for it. 

Solution 1: 

Append <portlet:namespace /> to the parameter. With this approach your data should look like this

 data: {
   <portlet:namespace />site: 'www.proliferay.com',
   <portlet:namespace />author: 'Hamidul Islam'
}

Solution 2:

 In the above solution the code does not look so good. To avoid this add the below two lines in your liferay-portlet.xml

<requires-namespaced-parameters>false</requires-namespaced-parameters>
<ajaxable>true</ajaxable>

Therefore your liferay-portlet.xml should look like below 

<portlet>
	<portlet-name>alloy-ajax-demo</portlet-name>
	<icon>/icon.png</icon>
	<requires-namespaced-parameters>false</requires-namespaced-parameters>
	<ajaxable>true</ajaxable>
	<header-portlet-css>/css/main.css</header-portlet-css>
	<footer-portlet-javascript>/js/main.js</footer-portlet-javascript>
	<css-class-wrapper>alloy-ajax-demo-portlet</css-class-wrapper>
</portlet>

In this approach you no need to append <portlet:namespace /> to the parameters 

3.Submit form data by Ajax

You can submit the whole form data by ajax. You just need to mention your form ID that you want to submit. In the below code we are submitting form data by form ID fm

<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<%@ taglib uri="http://liferay.com/tld/theme" prefix="theme" %>
<%@ taglib uri="http://liferay.com/tld/aui" prefix="aui" %>
<theme:defineObjects/>
<portlet:defineObjects />
<portlet:resourceURL var="resourceURL"/>
<script type="text/javascript">
function callServeResource(){
	AUI().use('aui-io-request', function(A){
		A.io.request('<%=resourceURL.toString()%>', {
			   method: 'post',
			   form: {
				   id: 'fm'
			   }
			});
	});
}
</script>
<form name="fm" id="fm">
Full Name:<input type="text" name="fullName"/>
<br/>
Age:<input type="text" name="age"/>
<br/>
<input type="button" value="Submit Form Data" onclick="callServeResource()">
</form>

Read submitted form data as below

@Override
	public void serveResource(ResourceRequest resourceRequest,
			ResourceResponse resourceResponse) throws IOException,
			PortletException {

		/**
		 * Read form data sent by AJAX
		 */

		String fullName = ParamUtil.getString(resourceRequest, "fullName");
		String age = ParamUtil.getString(resourceRequest, "age");

		System.out.println("The value of fullName  "+fullName);
		System.out.println("The value of age  "+age);

		super.serveResource(resourceRequest, resourceResponse);
	}

4.Receive data from server

Till now we have seen only how to submit data by AJAX. We can also receive data from server. In the below code we will send email id to serveResource method and serveResource will send back the full name of the user matching with the email id. 

<script type="text/javascript">
function callServeResource(){
	AUI().use('aui-io-request', function(A){
		A.io.request('<%=resourceURL.toString()%>', {
			   method: 'post',
			   form: {
				   id: 'fm'
			   },
			   on: {
				    success: function() {
				     alert(this.get('responseData'));
				    }
			   }
			});
	});
}
</script>
<form name="fm" id="fm">
Full Name:<input type="text" name="emailAddress"/>
<br/>
<input type="button" value="Submit Form Data" onclick="callServeResource()">
</form>

serveResource:

@Override
	public void serveResource(ResourceRequest resourceRequest,
			ResourceResponse resourceResponse) throws IOException,
			PortletException {

		/**
		 * Read form data sent by AJAX
		 */

		Long companyId = CompanyThreadLocal.getCompanyId();
		String emailAddress = ParamUtil.getString(resourceRequest, "emailAddress");
		User user = null;
		try {
			user = UserLocalServiceUtil.getUserByEmailAddress(companyId, emailAddress);
		} catch (PortalException e) {
			e.printStackTrace();
		} catch (SystemException e) {
			e.printStackTrace();
		}

		resourceResponse.setContentType("text/html");
		PrintWriter writer = resourceResponse.getWriter();
		if(user == null){
			writer.print("No matching with the email ID");
		}else{
			writer.print("Matches email id. The full name of the user: "+ user.getFullName());
		}
                writer.flush();
                writer.close();
		super.serveResource(resourceRequest, resourceResponse);
	}

5.Read JSON Data sent by server
serveResource method also can generate JSON data. With Alloy you can read JSON data easily. Below is the code

<script type="text/javascript">
function callServeResource(){
	AUI().use('aui-io-request', function(A){
		A.io.request('<%=resourceURL.toString()%>', {
			   method: 'post',
			   dataType: 'json',
			   form: {
				   id: 'fm'
			   },
			   on: {
				    success: function() {
				    	alert(this.get('responseData').fullName);
				    }
			   }
			});
	});
}
</script>
<form name="fm" id="fm">
Full Name:<input type="text" name="emailAddress"/>
<br/>
<input type="button" value="Submit Form Data" onclick="callServeResource()">
</form>

serveResource:

@Override
	public void serveResource(ResourceRequest resourceRequest,
			ResourceResponse resourceResponse) throws IOException,
			PortletException {

		/**
		 * Read form data sent by AJAX
		 */

		Long companyId = CompanyThreadLocal.getCompanyId();
		String emailAddress = ParamUtil.getString(resourceRequest, "emailAddress");
		User user = null;
		try {
			user = UserLocalServiceUtil.getUserByEmailAddress(companyId, emailAddress);
		} catch (PortalException e) {
			e.printStackTrace();
		} catch (SystemException e) {
			e.printStackTrace();
		}

		resourceResponse.setContentType("text/html");
		PrintWriter writer = resourceResponse.getWriter();
		JSONObject jsonObject =  JSONFactoryUtil.createJSONObject();
		if(user == null){
			jsonObject.put("fullName", "No matching with the email ID");
		}else{
			jsonObject.put("fullName", "Matches email id. The full name of the user: "+user.getFullName());
		}
		writer.print(jsonObject.toString());
		writer.flush();
		writer.close();
		super.serveResource(resourceRequest, resourceResponse);
	}

 


Call back function: You have seen only success as call back function till now. However this is not only the call back function. Here is the full list

1. start

2. complete

3. success

4.failure

5.end

We can assume that these are Life Cycle methods of Alloy Ajax Call. You can mention all the call back function like success. 

Tips:

1. Reuse of ajax connection 

You can define an ajax connection once and reuse multiple times. For example 

var ajaxRequest = A.io.request(‘<%=resourceURL.toString()%>’);
Later on you can use the connection as bellow

ajaxRequest.start();

2. autoLoad: false

autoLoad: false is used when you want to define only the ajax connection but not to call it for the first time. Later on you can use this connection var ajaxRequest = A.io.request(‘<%=resourceURL.toString()%>‘,

             {

                    autoLoad: false, …

           });

3. Set property or call methods dynamically for the ajax connection
Once you have ajax connection variable you can set different property like

ajaxRequest .start();

ajaxRequest .stop();

ajaxRequest .set(‘uri’, ‘some url’);

ajaxRequest .set(‘dataType’, ‘xml’);

ajaxRequest .set(‘method’, ‘GET’);

ajaxRequest .set(‘cache’, false);


 

Exit mobile version