Primefaces AJAX update= "@form"调用侦听器两次



我有一个页面,顶部有一些选项,当更改时会更新同一页面上的一些图表。以下是相关的过滤器部分:

<p:fieldset id="filtrosDashboard" legend="Filtros" toggleable="true" toggleSpeed="500" collapsed="#{beanJanela.filtroCollapsed}">
<!--Site filter-->
<div class="ui-g-12 ui-md-12 ui-lg-8">
<p:outputLabel for="ObrasPickList" value="#{beanJanela.tituloLabelSelecaoObrasFiltro}" styleClass="tituloFiltro"/>
<p:pickList id="ObrasPickList" value="#{beanJanela.obras}" var="obra" effect="slide"
itemValue="#{obra}" itemLabel="#{obra.descricao}"
showSourceFilter="true" showTargetFilter="true" showCheckbox="true"
filterMatchMode="contains" converter="obraConverter" responsive="true"
addLabel="Adicionar" addAllLabel="Adicionar tudo" 
removeLabel="Remover" removeAllLabel="Remover tudo"
rendered="#{beanJanela.showMultiplasObrasFiltro}">
<f:facet name="sourceCaption">Obras</f:facet>
<f:facet name="targetCaption">Selecionadas</f:facet>
<p:ajax event="transfer" listener="#{beanJanela.atualizaGraficos}" update="@form"/>
<p:column style="width: 92%">
<h:outputText value="#{obra.descricao}" />
</p:column>
</p:pickList>
</div>
<!--Date filter-->
<div class="ui-g-12 ui-md-12 ui-lg-4">
<p:outputLabel for="periodo" value="Período" styleClass="tituloFiltro" rendered="#{beanJanela.showPeriodoFiltro}"/>
<div class="ui-inputgroup">
<p:inputText id="periodo" value="#{beanJanela.periodo}" rendered="#{beanJanela.showPeriodoFiltro}">
<p:ajax event="change" listener="#{beanJanela.atualizaGraficos}" update="@form"/>
</p:inputText>
<span class="ui-inputgroup-addon"><i class="fa fa-fw fa-calendar"></i></span>
</div>
</div>
</p:fieldset>

如您所见,有两个过滤器,一个是带有工作站点的pickList,另一个是使用称为 daterangepicker 的 JavaScript 库转换为数据范围选择器的inputText

我为pickList定义了具有事件transfer<p:ajax/>,为inputText定义了另一个具有事件change<p:ajax/>,两者都调用相同的侦听器#{beanJanela.atualizaGraficos}并且它们都更新了包含过滤器和图形的表单。

问题是这样的,当我使用pickList它按预期工作时,方法atualizaGraficos只在后备 Bean 上调用一次;但是,如果我尝试使用日期过滤器进行过滤,则会调用两次方法atualizaGraficos

为什么会这样?我看过其他一些与此类似的问题相关的帖子,但就我而言,我有两个 ajax 调用,在同一表单内的两个不同组件上有两个不同的事件。

这是整页代码,以备不时之需:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:po="http://primefaces.org/omega">
<h:head>
<f:facet name="first">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta http-equiv="refresh" content="#{session.maxInactiveInterval};url=#{request.contextPath}/index.xhtml"/>
<title>Evop</title>
</f:facet>
<link rel="shortcut icon" type="image/png" href="/evop/resources/imagem/icone_evop.png"/>
<script type="text/javascript">
$(document).ready(function () {
$("form").bind("keypress", function (e) {
if (e.keyCode === 13) {
return false;
}
});
});
$(document).ready(function () {
$(window).keydown(function (event) {
if (event.keyCode === 13) {
return false;
}
});
});
</script>
<h:outputScript name="js/nanoscroller.js" library="resources" />
<h:outputScript name="js/layout.js" library="resources" />
<h:outputScript name="js/script.js" library="resources" />
<h:outputScript name="js/all.js" library="font-awesome" />
<h:outputStylesheet name="css/layout.css" library="resources" />
<h:outputStylesheet name="css/primeflex.css" library="resources" />
<h:outputStylesheet name="css/animate.css" library="resources" />
<h:outputStylesheet name="css/nanoscroller.css" library="resources" />
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.css" />
<h:outputStylesheet name="css/all.css" library="font-awesome"/>
<h:outputStylesheet name="css/styleCadastro.css" library="resources"/>
<h:outputStylesheet name="css/styleDashboards.css" library="resources"/>
<ui:insert name="head"/>
</h:head>
<h:body styleClass="main-body">
<div class="wrapper">
<div class="topbar clearfix">
<a id="omega-menu-button" href="#">
<span class="fa fa-bars"></span>
</a>
<span class="topbar-title">Dashboard</span>
</div>
<h:form id="menuform">
<div class="sidebar">
<div class="nano">
<div class="nano-content sidebar-scroll-content menu-flex">
<!--MENU-->
</div>
</div>
</div>
</h:form>
<div class="main">
<ui:param name="beanJanela" value="#{comprasDashboardsBean}" />
<h:form id="dashboardCompras" prependId="false">
<p:growl id="growl" showDetail="true" showSummary="true" sticky="false" escape="false"><p:autoUpdate/></p:growl>
<div style="margin-top: 15px;">
<div class="ui-g ui-g-fluid dashboard">
<!--Filterns-->
<div class="ui-g-12 filtro_obras filtro_obras2">      
<div class="filtro_card clearfix chatSummary">
<p:fieldset id="filtrosDashboard" legend="Filtros" toggleable="true" toggleSpeed="500" collapsed="#{beanJanela.filtroCollapsed}">
<!--Site filter-->
<div class="ui-g-12 ui-md-12 ui-lg-8">
<p:outputLabel for="ObrasPickList" value="#{beanJanela.tituloLabelSelecaoObrasFiltro}" styleClass="tituloFiltro"/>
<p:pickList id="ObrasPickList" value="#{beanJanela.obras}" var="obra" effect="slide"
itemValue="#{obra}" itemLabel="#{obra.descricao}"
showSourceFilter="true" showTargetFilter="true" showCheckbox="true"
filterMatchMode="contains" converter="obraConverter" responsive="true"
addLabel="Adicionar" addAllLabel="Adicionar tudo" 
removeLabel="Remover" removeAllLabel="Remover tudo"
rendered="#{beanJanela.showMultiplasObrasFiltro}">
<f:facet name="sourceCaption">Obras</f:facet>
<f:facet name="targetCaption">Selecionadas</f:facet>
<p:ajax event="transfer" listener="#{beanJanela.atualizaGraficos}" update="@form"/>
<p:column style="width: 92%">
<h:outputText value="#{obra.descricao}" />
</p:column>
</p:pickList>
</div>
<!--Date filter-->
<div class="ui-g-12 ui-md-12 ui-lg-4">
<p:outputLabel for="periodo" value="Período" styleClass="tituloFiltro" rendered="#{beanJanela.showPeriodoFiltro}"/>
<div class="ui-inputgroup">
<p:inputText id="periodo" value="#{beanJanela.periodo}" rendered="#{beanJanela.showPeriodoFiltro}">
<p:ajax event="change" listener="#{beanJanela.atualizaGraficos}" update="@form"/>
</p:inputText>
<span class="ui-inputgroup-addon"><i class="fa fa-fw fa-calendar"></i></span>
</div>
</div>
</p:fieldset>
</div>
</div>
<!--End of filters-->
<!-- SOME GRAPHS THAT ARE UPDATED WHEN THE FILTER CHANGES -->
<!-- SCRIPTS FOR THE DATE FILTER -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/momentjs/latest/moment.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.min.js"></script>
<h:outputScript name="js/dashboardExtender.js" library="resources" />
<script>
$(document).ready(function () {
var start = moment().subtract(29, 'days');
var end = moment();
function cb(start, end) {
$('#periodo').text(start.format('L') + ' - ' + end.format('L'));
}
$("#periodo").daterangepicker({
startDate: start,
endDate: end,
"locale": {
"format": "DD/MM/YYYY",
"separator": " - ",
"applyLabel": "Salvar",
"cancelLabel": "Cancelar",
"fromLabel": "De",
"toLabel": "Para",
"customRangeLabel": "Definir Período",
"weekLabel": "S",
"daysOfWeek": [
"Dom",
"Seg",
"Ter",
"Qua",
"Qui",
"Sex",

"Sab"
],
"monthNames": [
"Janeiro",
"Fevereiro",
"Março",
"Abril",
"Maio",
"Junho",
"Julho",
"Agosto",
"Setembro",
"Outubro",
"Novembro",
"Dezembro"
],
"firstDay": 1
},
ranges: {
'Últimos 7 Dias': [moment().subtract(6, 'days'), moment()],
'Últimos 15 Dias': [moment().subtract(14, 'days'), moment()],
'Últimos 30 Dias': [moment().subtract(29, 'days'), moment()],
'Esse Mês': [moment().startOf('month'), moment().endOf('month')],
'Último Mês': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]
}
}, cb);
cb(start, end);
});
</script>
</div>
</div>
</h:form>
</div>
</div>
<p:ajaxStatus onstart="PF('statusDialog').show();" oncomplete="PF('statusDialog').hide();">
<p:dialog widgetVar="statusDialog"
modal="true"
draggable="false"
closable="false"
resizable="false"
showHeader="false"
style="margin: 0; padding: 0;">
<p:graphicImage name="/imagem/ajax-loader.gif" />
</p:dialog>
</p:ajaxStatus>
</h:body>

我不知道为什么第二个 ajax 调用上的调用update="@form"触发了atualizaGraficos方法两次,而第一次 ajax 调用上的相同内容只触发了一次。

话虽如此,我的问题的解决方案是定义我想直接更新到第二个 ajax 调用的<p:ajax/>组件的更新标记中的图表的 ID。

如果您知道第一种方法两次更新表单的原因,请告诉我。