Как отправить форму с помощью Ajax-запроса в Liferay?

Я новичок в портале liferay. Я разработал один портлет в liferay для демонстрации. В этом примере я использовал взаимодействие между портлетами. Что я делаю: - У меня есть один поисковый портлет, в котором у меня есть одно текстовое поле для поиска. Когда я нажимаю кнопку поиска, он извлекает данные из базы данных и отображает эти данные с помощью поиска, содержащегося в другом портлете. Я использовал аннотации ProcessEvent и ActionEvent для этого проекта.

Теперь то, что я хочу, это когда я нажимаю кнопку поиска, тогда страница не должна обновляться (т.е. я хочу использовать концепцию AJAX), а данные должны отображаться в другом портлете.

Фрагмент кода

Портлет А — view.jsp

<%@include file="/html/init.jsp"%>
<portlet:defineObjects />

<!--

<portlet:actionURL var="actionURL" name="pitchBall"></portlet:actionURL>

//-->
**Change to Resource URL**
<portlet:resourceURL var="resourceURL">
</portlet:resourceURL>


<aui:form method="POST" action="<%= resourceURL%>" name="    <portlet:namespace>fm1</portlet:namespace>">
    <aui:input name="search" id="search" />
    <aui:button type="submit" name="Search" value="Search" />
</aui:form>

Портлет A — класс SearchPortlet

package com.test;

/**
 * Portlet implementation class SearchPortlet
 */
public class SearchPortlet extends GenericPortlet {

    @Override
    public void render(RenderRequest request, RenderResponse response)
            throws PortletException, IOException {
        // TODO Auto-generated method stub
        super.render(request, response);

    }

    @ProcessAction(name="pitchBall") 
    public void pitchBall(ActionRequest request, ActionResponse response) throws SystemException {
        String name = ParamUtil.getString(request, "search");       
        QName qName = new QName("http://liferay.com/events", "ipc.pitch");
        response.setEvent(qName, name);
    }

    public void init() {
        editJSP = getInitParameter("edit-jsp");
        helpJSP = getInitParameter("help-jsp");
        viewJSP = getInitParameter("view-jsp");
    }

    public void doEdit(
            RenderRequest renderRequest, RenderResponse renderResponse)
        throws IOException, PortletException {

        include(editJSP, renderRequest, renderResponse);
    }

    public void doHelp(
            RenderRequest renderRequest, RenderResponse renderResponse)
        throws IOException, PortletException {

        include(helpJSP, renderRequest, renderResponse);
    }

    @Override
    public void doView(
            RenderRequest renderRequest, RenderResponse renderResponse)
        throws IOException, PortletException {
        //super.doView(renderRequest, renderResponse);
        System.out.println("In doView code");

        renderResponse.setContentType(renderRequest.getResponseContentType());

        // file to display...
        String url = "/html/searchportlet/view.jsp";

        // read the above file and output it...
        getPortletContext().getRequestDispatcher(url).include(renderRequest, renderResponse);
        //include(viewJSP, renderRequest, renderResponse);
    }

    @Override
    public void serveResource(ResourceRequest request, ResourceResponse response)
            throws PortletException, IOException {
        // TODO Auto-generated method stub
        //super.serveResource(request, response);
         System.out.println("In serveResource code");

         response.setContentType("text/html");

         String name = request.getParameter("search");

         // this seems to be the page that was calling...?
         String resourceID = request.getResourceID();
         System.out.println("resourceId was : " + resourceID);


         System.out.println("message was : " + name);
         PrintWriter writer = response.getWriter();

         writer.print(name);
    }

    protected void include(
            String path, RenderRequest renderRequest,
            RenderResponse renderResponse)
        throws IOException, PortletException {

        PortletRequestDispatcher portletRequestDispatcher =
            getPortletContext().getRequestDispatcher(path);

        if (portletRequestDispatcher == null) {
            _log.error(path + " is not a valid include");
        }
        else {
            portletRequestDispatcher.include(renderRequest, renderResponse);
        }
    }

    protected String editJSP;
    protected String helpJSP;
    protected String viewJSP;

    private static Log _log = LogFactoryUtil.getLog(SearchPortlet.class);

}

Портлет Б — view.jsp

<%@include file="/html/init.jsp"%>
<portlet:defineObjects />

<%
String name = (String)renderRequest.getParameter("name");
%>

<liferay-ui:search-container
    emptyResultsMessage="author-empty-results-message">

    <liferay-ui:search-container-results
        results="<%= KeyurAuthorLocalServiceUtil.getStudentByName(name) %>" />

    <liferay-ui:search-container-row className="com.test.model.KeyurAuthor">

        <liferay-ui:search-container-column-text name="authorId"
            property="authorId" />
        <liferay-ui:search-container-column-text name="authorName"
            property="authorName" />
        <liferay-ui:search-container-column-text name="authorEmail"
            property="authorEmail" />
    </liferay-ui:search-container-row>

    <liferay-ui:search-iterator></liferay-ui:search-iterator>


</liferay-ui:search-container>

Портлет B — класс SearchResultPortlet

/**
 * Portlet implementation class SearchResultPortlet
 */
public class SearchResultPortlet extends GenericPortlet {

    public void init() {
        editJSP = getInitParameter("edit-jsp");
        helpJSP = getInitParameter("help-jsp");
        viewJSP = getInitParameter("view-jsp");
    }

    @ProcessEvent(qname="{http://liferay.com/events}ipc.pitch")
    public void catchBall(EventRequest request, EventResponse response) {
        Event event = request.getEvent();
        String name = (String)event.getValue();
        response.setRenderParameter("name", name);
    }

    public void doEdit(
            RenderRequest renderRequest, RenderResponse renderResponse)
    throws IOException, PortletException {

        include(editJSP, renderRequest, renderResponse);
    }

    public void doHelp(
            RenderRequest renderRequest, RenderResponse renderResponse)
    throws IOException, PortletException {

        include(helpJSP, renderRequest, renderResponse);
    }

    public void doView(
            RenderRequest renderRequest, RenderResponse renderResponse)
    throws IOException, PortletException {

        include(viewJSP, renderRequest, renderResponse);
    }

    protected void include(
            String path, RenderRequest renderRequest,
            RenderResponse renderResponse)
    throws IOException, PortletException {

        PortletRequestDispatcher portletRequestDispatcher =
            getPortletContext().getRequestDispatcher(path);

        if (portletRequestDispatcher == null) {
            _log.error(path + " is not a valid include");
        }
        else {
            portletRequestDispatcher.include(renderRequest, renderResponse);
        }
    }

    protected String editJSP;
    protected String helpJSP;
    protected String viewJSP;

    private static Log _log = LogFactoryUtil.getLog(SearchResultPortlet.class);

}

person Scorpion    schedule 14.02.2012    source источник


Ответы (3)


При выполнении ajax-запросов на портале ваш портлет должен реализовать

javax.portlet.ResourceServingPortlet

GenericPortlet уже делает это, но вы хотите переопределить его, и вместо использования <portlet:actionURL /> вы должны использовать <portlet:resourceURL /> из действия.

И в вашей настройке у вас должна быть форма поиска со скрытым полем для ключевых слов, и при нажатии кнопки отправки в портлете поиска вы должны скопировать ключевые слова из этой формы с помощью IPC в портлет результатов поиска и вызвать отправку по результату поиска из (без отправки формы в портлет поиска (A)).

Ваш класс SearchResultPortlet должен быть

public class SearchResultPortlet extends GenericPortlet {
    ...
    public void serveResource(ResourceRequest request, ResourceResponse response) throws PortletException, java.io.IOException {
       // do search and return result
    }
    ...
}

РЕДАКТИРОВАТЬ: полный пример

Форма поиска

import java.io.IOException;

import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;

public class SearchForm extends GenericPortlet {

    @Override
    protected void doView(RenderRequest p_request, RenderResponse p_response) throws PortletException, IOException {
        getPortletContext().getRequestDispatcher("/WEB-INF/jsp/search.jsp").include(p_request, p_response);
    }
}

Результат поиска

import java.io.IOException;

import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;

public class SearchResult extends GenericPortlet {

    @Override
    protected void doView(RenderRequest p_request, RenderResponse p_response) throws PortletException, IOException {
        getPortletContext().getRequestDispatcher("/WEB-INF/jsp/result.jsp").include(p_request, p_response);
    }

    @Override
    public void serveResource(ResourceRequest p_request, ResourceResponse p_response) throws PortletException, IOException {
                    //do your search here and put results in 'result'
        p_request.setAttribute("result", "results for: " + p_request.getParameter("search"));

        getPortletContext().getRequestDispatcher("/WEB-INF/jsp/html.jsp").include(p_request, p_response);
    }
}

search.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<%@ taglib uri="http://java.sun.com/portlet" prefix="portlet" %>

<portlet:defineObjects />

<script type="text/javascript">

    function doSearch() {
        Liferay.fire('searchKeywords', document.getElementById("<portlet:namespace/>search").value);    
    }

</script>

<form>
    <input type="text" name="search" id="<portlet:namespace/>search" />
    <button name="Search" value="Search" onclick="doSearch()" type="button">Search</button>
</form>

результат.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<%@ taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<%@ taglib uri="http://liferay.com/tld/aui" prefix="aui" %>

<portlet:defineObjects />
<portlet:resourceURL var="rurl" />

<script type="text/javascript">
    Liferay.on('searchKeywords', function(event, p_data){
        var A = AUI(); 
        A.use('aui-io-request', function(aui) {
            A.io.request("<%= rurl %>", { 
                method : 'POST', 
                data: {search: p_data},
                dataType : 'html', 
                on : { 
                    success : function() { 
                        AUI().one("#<portlet:namespace/>placeholder").html(this.get('responseData'));
                    } 
                } 
            });
        });
    });
</script>

Search Results:<br />
<div id="<portlet:namespace/>placeholder">
</div>

html.jsp (это для рендеринга результатов)

<%= request.getAttribute("result") %>
person Martin Gamulin    schedule 21.02.2012
comment
Спасибо за ответ. Я все еще сомневаюсь в этом. Как я могу передать значение моего текстового поля со скрытым полем в другой портлет? Он использует ActionRequest & Response, поэтому он обновит страницу. Не могли бы вы дать более подробную информацию об этом.... - person Scorpion; 21.02.2012
comment
И еще одна вещь, на которую я хотел бы указать, это то, что если я изменю его с action на resourceURL, тогда он вызовет метод serveResource SearchPortlet. Но как теперь передать его другому портлету с помощью IPC? - person Scorpion; 21.02.2012

Вы можете использовать связь между портлетами на стороне клиента. Назовем портлет A портлетом поиска, а портлет B — поиском, содержащимся в другом портлете. Я предполагаю, что вы используете Liferay 6+.

Шаг 1: нажатие кнопки поиска в портлете A вызовет в браузере следующую функцию javascript:

var A = AUI(); 
A.use('aui-io-request', 
    function(aui) {
        A.io.request(<portletA_serch_action_url>, { 
            method : 'GET', 
            dataType : 'json', 
            on : { 
                success : function() { 
                    Liferay.fire('myEvent', this.get('responseData');                    
                } 
            } 
        });
    }
);

Обратите внимание на вызов A.io.request(<portletA_serch_action_url>..., это URL-адрес действия на стороне сервера portletA. Дополнительную информацию о Liferay 6 и ajax см. в следующем блоге Liferay: http://www.liferay.com/web/nathan.cavanaugh/blog/-/blogs/alloyui-working-with-ajax.

Шаг 2: при ответе сервера portletA клиентская сторона portletA запускает событие с данными, полученными с сервера. Обратите внимание на вызов Liferay.fire('myEvent', this.get('responseData');. Это способ, которым Liferay поддерживает связь между портлетами на стороне клиента на стороне клиента (см. http://www.liferay.com/community/wiki/-/wiki/Main/Client).-side+Inter-Portlet+Communication).

myEvent — это событие, this.get('responseData'); — данные, полученные с сервера.

Шаг 3: портлет B на стороне клиента прослушивает myEvent и отображает данные

portletB будет прослушивать событие myEvent, а затем отображать данные:

Liferay.on(
 'myEvent',
 function(event, data){
   var portletId = data.portletId;
   var portlet = data.portlet;

   if(portletId.indexOf('YOUR_PORTLET_A_ID') > -1){
        alert(data);
   }
 }
 );

Обратите внимание на проверку происхождения данных из портлета A:

   if(portletId.indexOf('YOUR_PORTLET_A_ID') > -1){...

Вы можете удалить эту проверку, если у вас нет других портлетов, запускающих такое же событие.

Надеюсь, это поможет.

person Tony Rad    schedule 20.02.2012
comment
Спасибо за ваш добрый и быстрый ответ. Я попробую это и надеюсь, что это сработает.... - person Scorpion; 20.02.2012
comment
Я добавил фрагмент кода, не могли бы вы просто просмотреть его один раз и сообщить мне, где я ошибаюсь и что делать? Спасибо - person Scorpion; 21.02.2012

--------------------------JSP-код--------------------

  <portlet:resourceURL var="testAjaxResourceUrl"></portlet:resourceURL>

    <form id="testAjaxForm" action="">
        <input type="text" name="<portlet:namespace />param2">
        <input type="button" value="Submit" onclick="ajaxCall()">
    </form>
    
    <script type="text/javascript">
    function ajaxCall(){
       AUI().use('aui-base', 'io', 'aui-io-request', function(A){
            A.io.request('${testAjaxResourceUrl}', {
                   method: 'post',
                   data: {
                       <portlet:namespace />sampleParam: 'value2',
                   },
                   form:{
                       id:'testAjaxForm'
                   },
                   on: {
                           success: function() {
                            alert(this.get('responseData'));
                       }
                  }
            });
        });
    }
    </script> 

---------------------- Java-код-------------------------- ---

    @Override
            public void serveResource(ResourceRequest resourceRequest, ResourceResponse resourceResponse)
                    throws IOException, PortletException {
                
                
             String param = ParamUtil.getString(resourceRequest, "param2");
               
               System.out.println("Parameter is ==>" + param);
               
                resourceResponse.setContentType("text/html");
                PrintWriter out = resourceResponse.getWriter();
                out.print("You have entered ==>"+param);
                System.out.println("Ajax call is performed");
                out.flush();
                super.serveResource(resourceRequest, resourceResponse);
            }
person Parth    schedule 07.03.2021