primefaces の dataTable を使用すると、奇妙な動作が発生します。リストに新しい行を追加して dataTable を更新すると、ヘッダーが重複します。したがって、最初の行が追加された後、ヘッダーは 2 回表示され、2 行目以降は 4 回表示されます。フィルタリング オプションを削除しようとしましたが、それでも同じ動作になります。誰かが同じ問題を経験しましたか?Tomcat 7 で Primefaces 4.0 を使用しています。
私を助けてくれる人に前もって感謝し、私の貧弱な英語を申し訳ありません.
これは動作を示す画像です: http://i.imgur.com/tb57ahJ.png
これは私のコードです: index.xhtml ページには、dataTable を含む私の MovementList.xhtml ページが含まれています。
index.html
<!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:c="http://java.sun.com/jstl/core">
<h:head>
<link href="/#{COREWEB_MODULE_URL}/css/jsf.css" rel="stylesheet" type="text/css"></link>
</h:head>
<ui:include src="/jsp/faces/common/varImages.xhtml"/>
<h:body style="background-color:grey;">
<p:growl id="messages"/>
<p:dock position="top" halign="center" >
<p:menuitem value="Home" icon="#{imgHome64}" url="index.xhtml"/>
<p:menuitem value="Movimenti" icon="#{imgNoteBook64}" url="/movement/list.xhtml"/>
<p:menuitem value="Mutuo" icon="#{imgEuro64}" url="/bankLoan/list.xhtml"/>
<p:menuitem value="Grafici" icon="#{imgChart64}" url="/graph/list.xhtml"/>
<p:menuitem value="Dizionario" icon="#{imgBook64}" url="/dictionary/list.xhtml"/>
</p:dock>
<p:stack icon="/images/stack/stack.png">
<p:menuitem value="Home" icon="#{imgHome64}" url="index.xhtml"/>
<p:menuitem value="Movimenti" icon="#{imgNoteBook64}" url="/movement/list.xhtml"/>
<p:menuitem value="Mutuo" icon="#{imgEuro64}" url="/bankLoan/list.xhtml"/>
<p:menuitem value="Grafici" icon="#{imgChart64}" url="/graph/list.xhtml"/>
<p:menuitem value="Dizionario" icon="#{imgBook64}" url="/dictionary/list.xhtml"/>
</p:stack>
<div style="display:block;width:1300px;height:50px;">
<div style="float:left;width:1120px;" id="menuTopDiv">
</div>
<div style="float:left;width:180px;height:50px;" id="themeSwitcherDiv">
<h:panelGrid columns="2" cellpadding="10">
<p:themeSwitcher value="#{guestPreferences.theme}" style="width:165px" effect="fade" id="statefulSwitcher">
<f:selectItem itemLabel="Choose Theme" itemValue="" />
<f:selectItems value="#{themeSwitcherBean.themes}" />
<p:ajax listener="#{themeSwitcherBean.saveTheme}" />
</p:themeSwitcher>
</h:panelGrid>
</div>
</div>
<div style="display:block;width:1300px;height:220px;">
<div id="menuTopLeftDiv" style="float:left;width:300px;height:220px;">
<ui:include src="/jsp/faces/menu/menuLeft.xhtml"/>
</div>
<div id="latestIncomeDiv" style="float:left;width:490px;height:220px;margin-left:0.3em;">
<ui:include src="/jsp/faces/latestIncomeWidget.xhtml"/>
</div>
<div id="latestOutcomeDiv" style="float:left;width:496px;height:220px;margin-left:0.3em;">
<ui:include src="/jsp/faces/latestOutcomeWidget.xhtml"/>
</div>
</div>
<div style="float:left;display:block;width:1300px;">
<ui:include src="/jsp/faces/movement/movementList.xhtml"/>
</div>
</h:body>
</html>
動きリスト.xhtml
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:c="http://java.sun.com/jstl/core"
xmlns:p="http://primefaces.org/ui">
<h:form id="movementForm">
<h:outputScript library="primefaces" name="jquery/jquery.js"/>
<p:growl id="messages" showDetail="true"/>
<p:accordionPanel id="movementAccordion">
<p:tab title="Elenco Movimenti">
<p:dataTable id="dataTable" var="movement" value="#{movementJsf.movementList}" widgetVar="movementTable"
emptyMessage="No movements found with given criteria"
paginator="true" rows="10" editable="true" stickyHeader="true"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,15">
<p:column style="padding:0.2em;width:2.5em;text-align:center;" filterBy="#{movement.direction.name}"
headerText="Dir" filterMatchMode="contains">
<h:graphicImage url="#{movement.directionId == 3 ? imgArrowUpGreen16 : imgArrowDownRed16}"/>
</p:column>
<p:column style="padding:0.2em;" filterBy="#{movement.direction.name}"
headerText="Direzione" filterMatchMode="contains">
<h:outputText value="#{movement.direction.name}"/>
</p:column>
<p:column style="padding:0.2em;" filterBy="#{movement.type.name}"
headerText="Movimento" filterMatchMode="contains">
<h:outputText value="#{movement.type.name}"/>
</p:column>
<p:column style="padding:0.2em;width:6em;text-align:right;" headerText="Data">
<h:outputText value="#{movement.operationDate}">
<f:convertDateTime type="date" pattern="dd-MM-yyyy"/>
</h:outputText>
</p:column>
<p:column style="padding:0.2em;width:6em;text-align:right;" headerText="Ammontare">
<h:outputText value="#{movement.amount}">
<f:convertNumber type="currency" currencySymbol="€" locale="de-DE"/>
</h:outputText>
</p:column>
<p:column headerText="Azioni" style="padding:0.2em;width:6em;text-align:right;">
<h:graphicImage url="#{imgPageEdit}" title="Modifica" alt="Modifica" id="movement_edit_#{movement.id}"/>
<h:graphicImage url="#{imgPageDelete}" title="Cancella" alt="Cancella" id="movement_remove_#{movement.id}"/>
</p:column>
</p:dataTable>
</p:tab>
</p:accordionPanel>
<p:commandButton id="modalDialogButton" value="Aggiungi movimento" onclick="PF('movementFormDialog').show();" type="button"/>
<p:dialog id="modalDialog" header="Modal Dialog" widgetVar="movementFormDialog" modal="true" height="400" resizable="false"
showEffect="fade" hideEffect="fade">
<p:ajax event="close" update="messages" immediate="true" global="false"
listener="#{movementJsf.addMovement}"/>
<h:panelGrid id="display" columns="2" cellpadding="4">
<f:facet name="header">
Aggiungi movimento
</f:facet>
<h:outputLabel for="type" value="Tipologia: *"/>
<p:autoComplete value="#{movementJsf.typeId}" id="movementType" completeMethod="#{facesService.movementTypeAutocomplete}"
var="type" itemLabel="#{type.name}" itemValue="#{type.id}" forceSelection="true"/>
<h:outputLabel for="amount" value="Ammontare *"/>
<h:inputText size="20" value="#{movementJsf.amount}"/>
<h:outputLabel for="operationDate" value="Data operazione: *"/>
<p:calendar value="#{movementJsf.operationDate}" id="operationDateCalendar" locale="it" showButtonPanel="true" navigator="true" effect="slideDown"/>
<h:outputLabel for="estimated" value="Stimato: *"/>
<p:selectOneMenu value="#{movementJsf.estimatedId}" effect="fade">
<f:selectItem itemLabel="Seleziona" itemValue=""/>
<f:selectItems value="#{facesService.movementEstimatedList}" var="dictionary" itemLabel="#{dictionary.name}" itemValue="#{dictionary.id}"/>
</p:selectOneMenu>
<f:facet name="footer">
<p:commandButton type="button" value="Save" icon="ui-icon-check" style="margin:0"/>
</f:facet>
</h:panelGrid>
<p:commandButton id="addFormButton" value="Aggiungi" action="#{movementJsf.addMovement}"
oncomplete="PF('movementFormDialog').hide();" update="movementForm:movementAccordion:dataTable"/>
<p:commandButton id="undoFormButton" value="Annulla" onclick="PF('movementFormDialog').hide();" type="button"/>
</p:dialog>
</h:form>
</ui:composition>
MovementJsf.java
package it.fronte.account.jsf;
import it.fronte.account.command.search.MovementSearchCommand;
import it.fronte.account.model.Movement;
import it.fronte.account.service.AccountService;
import it.fronte.dictionary.model.Dictionary;
import it.fronte.dictionary.service.DictionaryService;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import org.springframework.web.jsf.FacesContextUtils;
@RequestScoped
@ManagedBean(name = "movementJsf")
public class MovementJsf {
protected AccountService accountService = (AccountService) FacesContextUtils.getWebApplicationContext(
FacesContext.getCurrentInstance()).getBean("accountService");
protected DictionaryService dictionaryService = (DictionaryService) FacesContextUtils.getWebApplicationContext(
FacesContext.getCurrentInstance()).getBean("dictionaryService");
// Properties
public BigDecimal amount;
public Integer estimatedId;
public Date operationDate = new Date();
public Integer typeId;
public List<Movement> movementList = new ArrayList<Movement>();
public List<Movement> getMovementList() {
MovementSearchCommand searchCommand = new MovementSearchCommand();
searchCommand.setAccountId(1);
searchCommand.setSort("operationDate");
searchCommand.setSortDirection("desc");
searchCommand.setPage(1);
searchCommand.setPageSize(99999999);
this.movementList = accountService.searchMovement(searchCommand);
return movementList;
}
// Getters & Setters
public Integer getTypeId() {
return typeId;
}
public void setTypeId(Integer typeId) {
this.typeId = typeId;
}
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
public Integer getEstimatedId() {
return estimatedId;
}
public void setEstimatedId(Integer estimatedId) {
this.estimatedId = estimatedId;
}
public Date getOperationDate() {
return operationDate;
}
public void setOperationDate(Date operationDate) {
this.operationDate = operationDate;
}
// Constructors
public MovementJsf() {
}
public MovementJsf(Integer typeId, BigDecimal amount, Date operationDate, Integer estimatedId) {
this.typeId = typeId;
this.amount = amount;
this.operationDate = operationDate;
this.estimatedId = estimatedId;
}
// CRUD methods
public String addMovement() {
Movement movement = new Movement();
movement.setAccountId(1);
movement.setCreationDate(new Date());
movement.setLastModifiedDate(new Date());
movement.setTypeId(this.typeId);
Dictionary type = dictionaryService.getDictionary(this.typeId);
movement.setDirectionId(getDirection(type));
movement.setAmount(this.amount);
movement.setEstimatedId(this.estimatedId);
movement.setOperationDate(this.operationDate);
accountService.saveOrUpdate(movement);
movementList.add(0, movement);
FacesMessage msg = new FacesMessage("Movimento aggiunto", "Movimento aggiunto");
FacesContext.getCurrentInstance().addMessage(null, msg);
return null;
}
private Integer getDirection(Dictionary dictionary) {
if (dictionary.getParentDictionaryId() != null)
return getDirection(dictionary.getParentDictionary());
else
return dictionary.getId();
}
}