• Alloy Ajax in Liferay Portlet

    Posted on October 11, 2014 by Hamidul Islam in Liferay.

    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?

    Note

    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);


     

    Post Tagged with , , , ,

5 Responses so far.

  1. Aravinth says:

    Nice explanation!!!!

  2. Phamvinh says:

    nice article but I think you need to post the code of project that everyone can study more easy!
    thank

  3. Dmitry says:

    Good article! Thanks

  4. Neil Carlo says:

    Very helpful! Thank you

Top
%d bloggers like this:

By continuing to use the site, you agree to the use of cookies. more information

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.

Close