ajax 如何在Liferay中使用Ajax请求提交表单?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9272930/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 11:07:49  来源:igfitidea点击:

How to submit form using Ajax request in Liferay?

ajaxliferayliferay-6

提问by Scorpion

I am newbie in liferay portal. I have developed one portlet in liferay for demo. I used inter portlet communication in this example. What i am doing is:- I have one search portlet in which i am having one textfield for search. When i click on search button it fetches the data from the database and display that data using search-contained in another portlet. I used ProcessEvent and ActionEvent annotation for this project.

我是liferay门户的新手。我在 liferay 中开发了一个用于演示的 portlet。我在这个例子中使用了 portlet 间的通信。我正在做的是:- 我有一个搜索 portlet,其中有一个用于搜索的文本字段。当我单击搜索按钮时,它会从数据库中获取数据并使用包含在另一个 portlet 中的搜索来显示该数据。我在这个项目中使用了 ProcessEvent 和 ActionEvent 注释。

Now what i want is when i click on the search button then the page should not be refresh(i.e i wish to use the concept of AJAX) and data should be displayed on the other portlet.

现在我想要的是当我点击搜索按钮时页面不应该刷新(即我希望使用 AJAX 的概念)并且数据应该显示在另一个 portlet 上。

Code Snippet

代码片段

Portlet A - view.jsp

Portlet A - 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>

Portlet A - SearchPortlet Class

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

}

Portlet B - view.jsp

Portlet B - 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>

Portlet B - SearchResultPortlet Class

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

}

回答by Martin Gamulin

When making ajax requests on portal your portlet should implemet

在门户上发出 ajax 请求时,您的 portlet 应该实现

javax.portlet.ResourceServingPortlet

GenericPortlet already does but you want to override it, and instead of using <portlet:actionURL />you should use <portlet:resourceURL />fro from action.

GenericPortlet 已经这样做了,但您想覆盖它,而不是使用<portlet:actionURL />您应该使用<portlet:resourceURL />fro from action。

And in your setup you should have search form with hidden field for keywords, and on clicking submit button in search portlet you should copy keywords from that form, with IPC, to search results portlet and invoke submit on search result from (without submitting form in search portlet (A)).

并且在您的设置中,您应该有带有关键字隐藏字段的搜索表单,并且在单击搜索 portlet 中的提交按钮时,您应该使用 IPC 从该表单复制关键字到搜索结果 portlet 并调用从搜索结果提交(不提交表单)搜索 portlet (A))。

Your SearchResultPortlet class should be

您的 SearchResultPortlet 类应该是

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

EDIT: complete example

编辑:完整示例

SearchForm

搜索表单

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

SearchResult

搜索结果

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

搜索.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>

result.jsp

结果.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 (this is for rendering results)

html.jsp(这是为了渲染结果)

<%= request.getAttribute("result") %>

回答by Tony Rad

You could use Inter portlet communication on the client side. Let's call portletA the search portlet and portletB the search-contained in another portlet. I'm assuming you are using Liferay 6+.

您可以在客户端使用 Inter portlet 通信。让我们将 portletA 称为搜索 portlet,将 portletB 称为搜索包含在另一个 portlet 中。我假设您使用的是 Liferay 6+。

Step 1: clicking the search button on portletA will trigger the folowing javascript function on the browser:

第一步:点击portletA上的搜索按钮,浏览器会触发以下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');                    
                } 
            } 
        });
    }
);

Note the call to A.io.request(<portletA_serch_action_url>...this is the portletA server side action url. See the following Liferay Blog for more information about Liferay 6 and ajax: http://www.liferay.com/web/nathan.cavanaugh/blog/-/blogs/alloyui-working-with-ajax.

请注意,A.io.request(<portletA_serch_action_url>...对此的调用是 portletA 服务器端操作 url。有关 Liferay 6 和 ajax 的更多信息,请参阅以下 Liferay 博客:http: //www.liferay.com/web/nathan.cavanaugh/blog/-/blogs/alloyui-working-with-ajax

Step 2: on portletA server response, portletA client side will launch an event with the data retrieved from the server. Note the call to Liferay.fire('myEvent', this.get('responseData');this is the way in which Liferay supports client side Inter Portlet Communication on the client side(See http://www.liferay.com/community/wiki/-/wiki/Main/Client-side+Inter-Portlet+Communication).

第 2 步:在 portletA 服务器响应上,portletA 客户端将使用从服务器检索到的数据启动一个事件。注意这个调用Liferay.fire('myEvent', this.get('responseData');是 Liferay 在客户端支持客户端 Inter Portlet 通信的方式(参见http://www.liferay.com/community/wiki/-/wiki/Main/Client-side+Inter-Portlet +沟通)。

myEventis the event fired, this.get('responseData');are the data retrieved from the server.

myEvent是触发事件,this.get('responseData');是从服务器检索的数据。

Step 3: client side portletB listen on myEvent and render the data

第 3 步:客户端 portletB 侦听 myEvent 并呈现数据

portletB will listen on myEvent and then render the data:

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

Note the check of the provenience of the data from portletA:

请注意对来自 portletA 的数据来源的检查:

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

You can remove that check if you don't have others portlets firing the same event.

如果您没有其他 portlet 触发相同的事件,您可以删除该检查。

Hope this help.

希望这有帮助。