我正在使用JSF Primefaces 5.3在Liferay 6.2上开发一个Web应用程序。网络应用程序在Tomcat上运行。我在同一页面上有 Portlet 1 和 Portlet 2。我想在用户与 Portlet 2 中的控件交互后,设置属于 Portlet 1 的某个后端对象的状态。
我尝试了一个基于事件的解决方案,效果很好。在我看来.xhtml我有这样的东西:
<p:selectOneMenu value="#{operationBox.selected}"
valueChangeListener="#{broker.operationChanged}" onchange="submit()"
style="width:50%">
<f:selectItems value="#{operationBox.operations}" />
</p:selectOneMenu>
代理类 (Portlet 2) 处理操作,在 ActionResponse 对象中设置定制事件,侦听器 (Portlet 1) 接收该事件。
但是,我不想提交表单,因为这会导致页面刷新,而我不需要。我不打算在 Portlet 1 中渲染任何内容。我的经纪人类看起来就像Liferay教程和演示应用程序中提供的示例:
public void submit() {
logger.debug("Submitting booking changes.");
QName qName = new QName("http://liferay.com/events", "ipc.customerEdited");
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
ActionResponse actionResponse = (ActionResponse) externalContext.getResponse();
actionResponse.setEvent(qName, bookingsModelBean.getCustomer());
}
我不知道是 ajax 还是 selectOneMenu
标签(或两者兼而有之)让我失望:如果我执行以下操作 <f:ajax event="change" listener="#{broker.handle}"/>
我的代理 Bean 得到的响应对象是 ResourceResponse
,我不能将其转换为 ActionResponse
以调用setEvent(QName qname, String string)
。
selectOneMenu
有没有办法触发对值更改的操作?操作是否仅与提交/页面重新加载相关联?
我需要一种方法将数据从 Portlet 2 发送到 Portlet 1 的服务器端。您认为我的最佳选择是什么?
多谢
使用最终解决方案进行编辑
事实证明,这不能通过当前规范的服务器端事件处理来完成。我最终设法用客户端javascript做到了这一点。仅当所涉及的 Portlet 位于同一页面上时,以下方法才有效:组件 1 - 火灾事件:
<p:selectOneMenu value="#{operationBox.selected}"
onchange="return myFireEvent('operation',this.value);>
和
<script>
function myFireEvent(caller, value) {
var payload = ...; // process your parameters
Liferay.fire('my-event-name', {
payload: payload
});
return false;
};
</script>
组件 2 - 接收事件:我用来将数据发送到服务器端的解决方法是通过<p:remoteCommand>
标签调用自定义 js 函数,您必须将其放置在<h:form>
中:
<p:remoteCommand name="handleEvent" actionListener="#{icpReceiver.handleEventJS}"/>
这是由Liferay API提供的js接收器函数调用的:
<script>
Liferay.on('my-event-name', function(event) {
handleEvent([{name:'payload', value:event.payload}]);
});
</script>
仅此而已。
你是对的 - JSR-286-portlet-communication 只涵盖动作(和事件)阶段,在渲染和资源阶段都不可用。规范出来得有点太早了,无法想象这一点。
您仍然可以执行基于 ajax 的 IPC,但您必须自己执行此操作 - 通常在前端,例如通过一个页面上的 Portlet 之间的 Javascript 通信。它不会是JSR-286-IPC。
一个相关的主题(但对于手头的具体情况不太有帮助)可能是Liferay的SPA(单页应用程序),其中您不再需要重新加载整页 - 而是门户处理和传输Portlet的增量状态,而您仍在构建经典Portlet。