Как отправить форму с помощью запроса Ajax в Liferay?
Я новичок в портале liferay. Я разработал один портлет в liferay для демонстрации. В этом примере я использовал связь между портлетами. Я делаю это: - У меня есть один портлет поиска, в котором у меня есть одно текстовое поле для поиска. Когда я нажимаю кнопку поиска, он извлекает данные из базы данных и отображает эти данные, используя поиск, содержащийся в другом портлете. Я использовал аннотации ProcessEvent и ActionEvent для этого проекта.
Теперь то, что я хочу, - это когда я нажимаю кнопку поиска, тогда страница не должна обновляться (например, я хочу использовать концепцию AJAX), и данные должны отображаться на другом портлете.
Фрагмент кода
Портлет 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>
Портлет 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);
}
Портлет 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>
Портлет 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);
}
Ответы
Ответ 1
При создании ajax-запросов на портале ваш портлет должен реализовывать
javax.portlet.ResourceServingPortlet
GenericPortlet уже делает, но вы хотите переопределить его, и вместо использования <portlet:actionURL />
вы должны использовать <portlet:resourceURL />
fro от действия.
И в вашей настройке вы должны иметь форму поиска со скрытым полем для ключевых слов, а при нажатии кнопки отправки в поисковом портлете вы должны скопировать ключевые слова из этой формы с помощью 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
}
...
}
EDIT: полный пример
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
<%@ 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
<%@ 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") %>
Ответ 2
Вы можете использовать меж портлетную связь на стороне клиента.
Позвольте вызвать портлетИ портлет поиска и портлетB, содержащий поиск в другом портлете.
Я предполагаю, что вы используете Liferay 6 +.
Шаг 1: нажатие кнопки поиска на портлетеА вызовет следующую функцию 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 для получения дополнительной информации о Liferay 6 и ajax: http://www.liferay.com/web/nathan.cavanaugh/blog/-/blogs/alloyui-working-with-ajax.
Шаг 2: при ответе сервера portletA, portletA клиентская сторона запустит событие с данными, полученными с сервера.
Обратите внимание на вызов Liferay.fire('myEvent', this.get('responseData');
, так как Liferay поддерживает клиентскую часть Inter Portlet Communication на стороне клиента (см. 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);
}
}
);
Обратите внимание на проверку происхождения данных из portletA:
if(portletId.indexOf('YOUR_PORTLET_A_ID') > -1){...
Вы можете удалить эту проверку, если у вас нет других портлетов, запускающих одно и то же событие.
Надеюсь на эту помощь.