Primefaces datatable duplicates data on deletion - ajax

im using hibernate 4, spring 4, lucene 3, primefaces 5, java 7.
I got a data table, which data is populated on the baking bean, the idea with the table is that it shows me some uncategorized words, and lets me categorizate them.
an example of the initial table looks normal for example
1 2 3 4 5
here is my page
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:form id="form">
<p:growl id="msgs" showDetail="true" life="2000" />
<p:dataTable id="words" var="word"
value="#{wordCatalogatorController.unknownWords}" editable="true"
style="margin-bottom:20px">
<f:facet name="header">Row Editing</f:facet>
<p:ajax event="rowEdit"
listener="#{wordCatalogatorController.onRowEdit}" update=":form:msgs" />
<p:ajax event="rowEditCancel"
listener="#{wordCatalogatorController.onRowCancel}" update=":form:msgs" />
<p:column headerText="Palabra">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{word.word}" />
</f:facet>
<f:facet name="input">
<h:outputText value="#{word.word}" />
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Tipo Palabra">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{word.wordType}" />
</f:facet>
<f:facet name="input">
<h:selectOneMenu value="#{word.wordType}" style="width:100%"
converter="#{wordTypeConverter}">
<f:selectItems value="#{wordCatalogatorController.wordTypes}"
var="man" itemLabel="#{man.wordType}" itemValue="#{man}" />
</h:selectOneMenu>
</f:facet>
</p:cellEditor>
</p:column>
<p:column style="width:32px">
<p:rowEditor />
</p:column>
</p:dataTable>
</h:form>
</html>
the bean for this is:
#Controller
#Transactional
public class WordCatalogatorController {
private List<Word> unknownWords = new ArrayList<Word>();
private List<WordType> wordTypes = new ArrayList<WordType>();
public WordCatalogatorController(){
//inicializamos palabras desconocidas y tipos de palabras!
for(int i = 0 ; i < 6 ; i++){
unknownWords.add(new Word("" + i));
}
for(int i = 0 ; i < 4 ; i++){
wordTypes.add(new WordType("" + i));
}
}
public void onRowEdit(RowEditEvent event) {
Word currentWord = (Word) event.getObject();
unknownWords.remove(currentWord);
}
public void onRowCancel(RowEditEvent event) {
FacesMessage msg = new FacesMessage("Edit Cancelled",
((Word) event.getObject()).getWord());
FacesContext.getCurrentInstance().addMessage(null, msg);
}
public void onCellEdit(CellEditEvent event) {
Object oldValue = event.getOldValue();
Object newValue = event.getNewValue();
if (newValue != null && !newValue.equals(oldValue)) {
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO,
"Cell Changed", "Old: " + oldValue + ", New:" + newValue);
FacesContext.getCurrentInstance().addMessage(null, msg);
}
}
then after editing and saving the first row (1) the datatables updates with 1 2 2 3 4 5
Any ideas will be really apreciated!
here comes the code for pojo clases
#Entity
#Table(name="Word")
#Indexed
#AnalyzerDef(name = "searchtokenanalyzer",tokenizer = #TokenizerDef(factory = StandardTokenizerFactory.class),
filters = {
#TokenFilterDef(factory = StandardFilterFactory.class),
#TokenFilterDef(factory = LowerCaseFilterFactory.class),
#TokenFilterDef(factory = StopFilterFactory.class,params = {
#Parameter(name = "ignoreCase", value = "true") }) })
#Analyzer(definition = "searchtokenanalyzer")
public class Word {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long wordId;
#Column(name="word")
#Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
#Analyzer(definition="searchtokenanalyzer")
private String word;
#ManyToMany(mappedBy="words")
private Collection<Danger> dangers = new ArrayList<Danger>();
#ManyToMany(mappedBy="words")
private Collection<Risk> risks = new ArrayList<Risk>();
#ManyToMany(mappedBy="words")
private Collection<Control> controls = new ArrayList<Control>();
#ManyToOne
#JoinColumn(name = "wordTypeId")
private WordType wordType;
public Word(String word, WordType wordType) {
super();
this.word = word;
this.wordType = wordType;
}
public Word(String word) {
super();
this.word = word;
}
#Override
public boolean equals(Object obj) {
if(obj instanceof Word){
return ((Word)obj).getWord().equalsIgnoreCase(this.getWord());
}else{
return false;
}
}
public Word() {
super();
}
public long getWordId() {
return wordId;
}
public void setWordId(long wordId) {
this.wordId = wordId;
}
#Entity
#Table(name = "WordType")
#Indexed
public class WordType {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long wordTypeId;
#Column(name = "wordType")
#Field(index = Index.YES, analyze = Analyze.YES, store = Store.NO)
#Analyzer(definition = "searchtokenanalyzer")
private String wordType;
#Column(name = "description")
private String description;
#OneToMany(mappedBy = "wordType")
private Set<Word> words;
#Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
if (!(obj instanceof WordType)) {
return false;
} else {
WordType extenalWT = (WordType) obj;
if (this.wordType.equalsIgnoreCase(extenalWT.getWordType())
&& this.wordTypeId == extenalWT.getWordTypeId()) {
return true;
} else {
return false;
}
}
}
public WordType() {
}
public WordType(String wordType) {
this.wordType = wordType;
}
public long getWordTypeId() {
return wordTypeId;
}
public void setWordTypeId(long wordTypeId) {
this.wordTypeId = wordTypeId;
}
public String getWordType() {
return wordType;
}
public void setWordType(String wordType) {
this.wordType = wordType;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Set<Word> getWords() {
return words;
}
public void setWords(Set<Word> words) {
this.words = words;
}
#Override
public String toString() {
return wordType;
}
}

For anyone else having this issue:
It seems to be an issue between the rowEditor and the table sorting. Having the correct update target on the ajax tag isn't an issue as the row is technically removed but the display gets messed up. You can get around this with just a touch of nastiness. You can force a filter during oncomplete for the ajax tag. This will get rid of the ghost duplicate record.
<p:ajax event="rowEdit"
listener="#{beanName.onRowEdit}"
update=":growl :messages :formName:tableId"
oncomplete="PF('tableWidgetVar').filter();" />

Finally the best solution was to implement the select event for the data table, and in the event have a dialog to pick the option, then refresh the table, this is the final xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<h:form id="myForm">
<p:growl id="msgs" showDetail="true" life="2000" />
<p:panel header="Sale Item" style="width: 400px;">
<h:panelGrid columns="2" cellpadding="5">
<p:outputLabel value="Texto" for="acSimple" />
<p:autoComplete id="acSimple"
value="#{wordCatalogatorController.texto}"
completeMethod="#{wordCatalogatorController.completeText}"
binding="#{wordCatalogatorController.autoCompleteText}" />
<p:commandButton value="Guardar actividad" id="save"
update=":myForm:msgs words"
binding="#{wordCatalogatorController.saveButton}"
actionListener="#{wordCatalogatorController.saveActivity}"
styleClass="ui-priority-primary" process="#this" />
</h:panelGrid>
<p:dataTable id="words" widgetVar="words" var="word"
value="#{wordCatalogatorController.unknownWords}" editable="true"
style="margin-bottom:20px" rowKey="#{word.word}"
selection="#{wordCatalogatorController.selectedWord}"
selectionMode="single" editMode="row">
<p:ajax event="rowSelect"
listener="#{wordCatalogatorController.changeClient}"
oncomplete="PF('activityDialog').show()"
update=":myForm:activityDialog" />
<f:facet name="header">Edicion de palabras</f:facet>
<p:column headerText="Palabra">
<h:outputText value="#{word.word}" />
</p:column>
<p:column headerText="Edicion">
<h:outputText value="Presione para catalogar la palabra" />
</p:column>
</p:dataTable>
</p:panel>
<p:dialog id="activityDialog" width="500px" height="600px"
header="Palabra a catalogar: #{wordCatalogatorController.selectedWord.word}"
widgetVar="activityDialog" modal="true" closable="false">
<h:panelGrid columns="2" cellpadding="5">
<p:selectOneMenu id="wordTypes"
value="#{wordCatalogatorController.selectedWordType}"
style="width: 150px;" converter="#{wordTypeConverter}">
<p:ajax
listener="#{wordCatalogatorController.wordTypeChangeListener}"
update=":myForm:words" />
<f:selectItem itemLabel="" itemValue="" />
<f:selectItems value="#{wordCatalogatorController.wordTypes}" />
</p:selectOneMenu>
</h:panelGrid>
</p:dialog>
</h:form>
</h:body>
</html>

Related

update dataTable depending on the value chosen in selectOneMenu

I'm using a selectOneMenu and i want to update datatable depending on what i choose on the combobox, i have two tables on the database:
Fournisseur
idFournisseur
raisonSociale
telephone..
and
Devis
idDevis
idFournisseur
devis.xhtml
<h:form id="form">
<p:growl id="msgs" showDetail="true"/>
<p:outputLabel for="console" value="Basic:" />
<p:selectOneMenu id="console" value="#{fournisseurBean.raisonSociale}">
<f:selectItems value="#{fournisseurBean.listeFournisseurs}" var="fournisseur" itemValue="#{fournisseur}" itemLabel="#{fournisseur.raisonSociale}" />
<p:ajax event="change" update="display" listener="#{fournisseurBean.getFournisseurByRaison()}" />
</p:selectOneMenu>
<p:dataTable id="display" var="listeDevis" value="#{devisBean.listeDevis}" editable="true" style="margin-bottom:10px">
<f:facet name="header">
Liste des devis
</f:facet>
<p:ajax event="rowEdit" listener="#{dtEditView.onRowEdit}" update=":form:msgs" />
<p:ajax event="rowEditCancel" listener="#{dtEditView.onRowCancel}" update=":form:msgs" />
<p:column headerText="Id devis">
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{listeDevis.idDevis}" /></f:facet>
<f:facet name="input"><p:inputText id="modelInput" value="#{listeDevis.idDevis}" style="width:100%"/></f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Date devis">
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{listeDevis.dateDevis}" /></f:facet>
<f:facet name="input"><p:inputText value="#{listeDevis.dateDevis}" style="width:100%" label="Year"/></f:facet>
</p:cellEditor>
</p:column>
<p:column style="width:32px" headerText="Modification">
<p:rowEditor />
</p:column>
</p:dataTable>
</h:form>
FournisseurBean.xhtml
package controller;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.event.ValueChangeEvent;
import model.services.FournisseurMetier;
import net.vo.Fournisseur;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
#Component
#Scope("view")
public class FournisseurBean {
#Autowired
private FournisseurMetier fournisseurMetier;
private List<Fournisseur> listeFournisseurs;
private List<String> listeRaisons;
private int idFournisseur;
private String raisonSociale;
private String rib;
private String adresse;
private Long telephone;
#PostConstruct
public void init() {
listeFournisseurs = fournisseurMetier.getAllFournisseurs();
listeRaisons = fournisseurMetier.getAllRaisonsSociales();
}
public List<Fournisseur> getListeFournisseurs() {
return listeFournisseurs;
}
public void insert()
{
Fournisseur fournisseur = new Fournisseur();
fournisseur.setIdFournisseur(getIdFournisseur());
fournisseur.setRaisonSociale(getRaisonSociale());
fournisseur.setRib(getRib());
fournisseur.setAdresse(getAdresse());
fournisseur.setTelephone(getTelephone());
fournisseurMetier.insert(fournisseur);
}
public void update()
{
Fournisseur fournisseuur = fournisseurMetier.getFournisseur(this.idFournisseur);
fournisseuur.setRaisonSociale(getRaisonSociale());
fournisseuur.setRib(getRib());
fournisseuur.setAdresse(getAdresse());
fournisseuur.setTelephone(getTelephone());
fournisseurMetier.update(fournisseuur);
}
public FournisseurMetier getFournisseurMetier() {
return fournisseurMetier;
}
public void setFournisseurMetier(FournisseurMetier fournisseurMetier) {
this.fournisseurMetier = fournisseurMetier;
}
public void setListeFournisseurs(List<Fournisseur> listeFournisseurs) {
this.listeFournisseurs = listeFournisseurs;
}
public int getIdFournisseur() {
return idFournisseur;
}
public void setIdFournisseur(int idFournisseur) {
this.idFournisseur = idFournisseur;
}
public String getRaisonSociale() {
return raisonSociale;
}
public void setRaisonSociale(String raisonSociale) {
this.raisonSociale = raisonSociale;
}
public String getRib() {
return rib;
}
public void setRib(String rib) {
this.rib = rib;
}
public Long getTelephone() {
return telephone;
}
public void setTelephone(Long telephone) {
this.telephone = telephone;
}
public String getAdresse() {
return adresse;
}
public void setAdresse(String adresse) {
this.adresse = adresse;
}
#Override
public String toString() {
return "FournisseurBean{" + "raisonSociale=" + raisonSociale + '}';
}
public void getFournisseurByRaison()
{
System.out.println(raisonSociale);
}
}
This method getFournisseurByRaison() shows me a reference to object Fournisseur not the attribute raisonSociale.
You can sue p:ajax as you mentioned in comments.
OR
Since you are using Primefaces you can also Update any component from ManagedBean itself using org.primefaces.context.RequestContext object.
For example:
Facelet:
<h:form id="form1">
<p:dataTable id="myTab">
...
</p:dataTable>
</h:form>
ManagedBean:
RequestContext reqCtx = Requestcontext.getCurrentInstance();
req.Ctx.update("form1:myTab");
this method getFournisseurByRaison() shows me a reference to object Fournisseur not the attribure raisonSociale
This is because you're setting the object as the value:
<!-- itemValue="#{fournisseur}" <= here is the object set as value -->
<f:selectItems value="#{fournisseurBean.listeFournisseurs}"
var="fournisseur"
itemValue="#{fournisseur}"
itemLabel="#{fournisseur.raisonSociale}" />
You should use an identifier or another field to be able to seek the selected fournisseur from the values of the list. This may be a starting approach:
<!-- itemValue="#{fournisseur.id}" <= or another unique identifier field -->
<f:selectItems value="#{fournisseurBean.listeFournisseurs}"
var="fournisseur"
itemValue="#{fournisseur.id}"
itemLabel="#{fournisseur.raisonSociale}" />
Then, in your bean:
public void getFournisseurByRaison() {
System.out.println(raisonSociale); //will print the user selected id or unique identifier
//access to devisBean and update the data in `devisBean.listeDevis` in there
}

JSF multiple ajax event on a single page

I have the following xhtml page where there is a form where the user have to select the location where he wants to travel; choosing it from a selectionmenu, the panel "Volo" is updated by an action listener and it will contain another selectionmenu where all flights to that location are available. I'd like to select the Hotels and Escursions available between the starting and ending date of the flight, so i used an action listener to update the panel containing the two activities based on the flight chosen. I'd like to know where i'm mistaking and if it's possible to have multiple updates of this kind in a single page.
I post the code of the xhtml page:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<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">
<h:head>
<title>Add a Default Package</title>
</h:head>
<h:body>
<h:form id="form">
<p:panel header="DefaultPackage Form">
<h:panelGrid columns="3" id="regGrid">
<h:outputLabel for="Name">Name:</h:outputLabel>
<p:inputText id="Name"
value="#{addDefaultPackageBean.defpackDTO.name}" />
<p:message for="Name" />
<h:outputLabel for="location">Locations Available:</h:outputLabel>
<h:selectOneMenu for="location" value="#{addDefaultPackageBean.defpackDTO.location}">
<f:ajax listener="#{addDefaultPackageBean.Search()}" render=":form:Volo" />
<f:selectItems id="location" value="#{addDefaultPackageBean.availableLocations}" />
</h:selectOneMenu>
</h:panelGrid>
</p:panel>
<p:panel header="Voli Disponibili per la location selezionata" id="Volo" rendered="#{addDefaultPackageBean.flag}" >
<h:outputLabel for="Fly">Volo:</h:outputLabel>
<h:selectOneMenu for="Fly" value="#{addDefaultPackageBean.fly}">
<f:ajax listener="#{addDefaultPackageBean.sel()}" render=":form:regularGrid" />
<f:selectItems id="Fly" value="#{addDefaultPackageBean.elelisfly}"
var="ElementDTO" itemValue="#{ElementDTO.name}"
itemLabel="#{ElementDTO.name}" />
</h:selectOneMenu>
</p:panel>
<p:panel header="HotelEsc" id="HotelEscursioni">
<h:panelGrid columns="3" id="regularGrid" rendered="#{addDefaultPackageBean.flagdopo}">
<h:outputLabel for="Hotel">Hotel:</h:outputLabel>
<h:selectOneMenu for="Hotel" value="#{addDefaultPackageBean.hotel}">
<f:selectItems id="Hotel"
value="#{addDefaultPackageBean.elelishotel}" var="ElementDTO"
itemValue="#{ElementDTO.name}" itemLabel="#{ElementDTO.name}" />
</h:selectOneMenu>
<p:message for="Hotel" />
<h:outputLabel for="Escursion">Escursioni:</h:outputLabel>
<f:facet name="header">Clicca su view per vedere i dettagli</f:facet>
<p:dataTable id="Escursion" var="esc"
value="#{addDefaultPackageBean.elelisescursion}"
rowKey="#{esc.name}"
selection="#{addDefaultPackageBean.selectedEscursions}"
selectionMode="multiple">
<p:column headerText="Nome"> #{esc.name} </p:column>
<p:column headerText="Costo"> #{esc.cost} </p:column>
<p:column headerText="Data Iniziale"> #{esc.startingDate} </p:column>
<p:column headerText="Data Fine"> #{esc.endingDate} </p:column>
<f:facet name="footer">
<p:commandButton value="View" icon="ui-icon-search"
oncomplete="PF('escursionDialog').show()" />
</f:facet>
</p:dataTable>
<p:dialog header="Escursion Detail" widgetVar="escursionDialog"
width="250" showEffect="explode" hideEffect="explode">
<p:dataList id="display"
value="#{addDefaultPackageBean.selectedEscursions}"
var="selectedEsc" type="definition">
Nome: #{selectedEsc.name}, Description: #{selectedEsc.description}
</p:dataList>
</p:dialog>
</h:panelGrid>
</p:panel>
<p:commandButton value="Add" update="regGrid"
action="#{addDefaultPackageBean.add()}" />
</h:form>
</h:body>
</html>
Bean page:
package beans;
import java.awt.Event;
import java.io.Serializable;
import java.util.ArrayList;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.enterprise.context.SessionScoped;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.view.ViewScoped;
import elementManagement.ElementMgr;
import elementManagementDTO.ElementDTO;
import DefaultPackageManagement.DefaultPackageMgr;
import DefaultPackageManagementDTO.DefaultPackageDTO;
#ManagedBean(name="addDefaultPackageBean") //come viene richiamato
#ViewScoped
public class AddDefaultPackageBean implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
#EJB
private DefaultPackageMgr defpackMgr;
private DefaultPackageDTO defpackDTO;
private ArrayList<ElementDTO> elelisfly;
private ArrayList<ElementDTO> elelishotel;
private ArrayList<ElementDTO> elelisescursion;
private ArrayList<ElementDTO> elelis;
private ElementDTO[] selectedEscursions;
private String fly;
private String hotel;
private boolean flag=true;
private boolean flagdopo=true;
private ArrayList<String> availableLocations;
private ElementDTO flyElem;
#EJB
private ElementMgr elemMgr;
public ElementDTO[] getSelectedEscursions() {
return selectedEscursions;
}
public void setSelectedEscursions(ElementDTO[] selectedEscursions) {
this.selectedEscursions = selectedEscursions;
}
public AddDefaultPackageBean() {
defpackDTO = new DefaultPackageDTO();
}
#PostConstruct
public void init()
{
this.elelisfly=new ArrayList<ElementDTO>();
this.elelishotel=new ArrayList<ElementDTO>();
this.elelisescursion=new ArrayList<ElementDTO>();
this.setElelis(elemMgr.getAllElements());
this.availableLocations=new ArrayList<String>();
for(ElementDTO e:elelis)
{
if (this.availableLocations.contains(e.getLocation())==false)
{
this.availableLocations.add(e.getLocation());
}
}
}
public String add() {
this.AssignElemFlyFromSelection();
this.AssignElemHotelFromSelection();
this.AssignElemEscursionFromSelection();
defpackMgr.save(defpackDTO);
return "/employee/index?faces-redirect=true";
}
public void sel()
{
System.out.print("ehila" );
this.AssignElemFlyFromSelection();
this.elelisescursion.clear();
this.elelishotel.clear();
for(ElementDTO e:elelis)
{
System.out.print("ho un hotel tra gli elementi "+e.getName() );
if(e.getType().equals("Hotel"))
{
System.out.print("ho un hotel tra gli elementi "+e.getName() );
if(e.getStartingDate().after(this.flyElem.getStartingDate())&&(e.getEndingDate().before(this.flyElem.getEndingDate())))
{
System.out.print("ho un hotel tra gli elementi con le date giuste"+e.getName());
this.getElelishotel().add(e);
}
}
else
{
if(e.getType().equals("Escursion"))
{
if(e.getStartingDate().after(this.flyElem.getStartingDate())&&(e.getEndingDate().before(this.flyElem.getEndingDate())))
{
this.getElelishotel().add(e);
}
}
}
}
this.setFlagdopo(true);
}
public DefaultPackageDTO getDefpackDTO() {
return defpackDTO;
}
public void setDefpackDTO(DefaultPackageDTO defpackDTO) {
this.defpackDTO = defpackDTO;
}
public ArrayList<ElementDTO> getElelisfly() {
return elelisfly;
}
public void setElelisfly(ArrayList<ElementDTO> elelisfly) {
this.elelisfly = elelisfly;
}
public ArrayList<ElementDTO> getElelishotel() {
return elelishotel;
}
public void setElelishotel(ArrayList<ElementDTO> elelishotel) {
this.elelishotel = elelishotel;
}
public ArrayList<ElementDTO> getElelisescursion() {
return elelisescursion;
}
public void setElelisescursion(ArrayList<ElementDTO> elelisescursion) {
this.elelisescursion = elelisescursion;
}
public String getFly() {
return fly;
}
public void setFly(String fly) {
this.fly = fly;
}
public String getHotel() {
return hotel;
}
public void setHotel(String hotel) {
this.hotel = hotel;
}
private void AssignElemFlyFromSelection()
{
for (ElementDTO elem:this.elelisfly)
{
if(elem.getName().equals(this.fly))
{
this.flyElem=elem;
}
}
}
private void AssignElemHotelFromSelection()
{
for (ElementDTO elem:this.elelishotel)
{
if(elem.getName().equals(this.hotel))
{
this.defpackDTO.getElem().add(elem);
}
}
}
private void AssignElemEscursionFromSelection()
{
for(int i=0;i<selectedEscursions.length;i++)
{
this.defpackDTO.getElem().add(selectedEscursions[i]);
}
}
public void Search(){
String s=defpackDTO.getLocation();
System.out.print("luogo scelto "+s);
this.setElelis(this.elemMgr.getAllElementsByLocation(s));
for(ElementDTO e:elelis)
{
System.out.print("aggiungo volo "+e.getName());
if(e.getType().equals("Flight"))
{
this.getElelisfly().add(e);
System.out.print("aggiungo volo "+e.getName());
}
}
this.setFlag(true);
}
public ArrayList<ElementDTO> getElelis() {
return elelis;
}
public void setElelis(ArrayList<ElementDTO> elelis) {
this.elelis = elelis;
}
public ArrayList<String> getAvailableLocations() {
return availableLocations;
}
public void setAvailableLocations(ArrayList<String> availableLocations) {
this.availableLocations = availableLocations;
}
public Boolean getFlag() {
return flag;
}
public void setFlag(Boolean flag) {
this.flag = flag;
}
public boolean isFlagdopo() {
return flagdopo;
}
public void setFlagdopo(boolean flagdopo) {
this.flagdopo = flagdopo;
}
public ElementDTO getFlyElem() {
return flyElem;
}
public void setFlyElem(ElementDTO flyElem) {
this.flyElem = flyElem;
}
}
Yes , it is possible to update multiple components in single command button.
<p:commandButton value="Add" update="regGrid ,anothercomponent,anothercomponent2" />

Ajax update breaks Primefaces datatable functionality

In my application I have a PF layout with a Tree node on west part, and a content part on center where I want to load different pages dynamically with ajax technology.
To get it, this content part contains an ui:include tag with EL expression. When the user clicks a tree node button, a page is rendered correctly on the center (and that works pretty well!). But some functionality of datatable such as sorting is broken or lost.
Moreover, if a refresh completely the page from the web browser all works OK.
I have simplified my project in order to give you a clean example.
The index.xhtml:
<p:layout fullPage="true">
<p:layoutUnit position="north" size="100" header="Top">
</p:layoutUnit>
<p:layoutUnit position="west" size="100" resizable="true">
<h:form>
<p:tree id="menuTree"
value="#{menuController.root}"
var="node"
selection="#{menuController.selectedNode}"
selectionMode="single">
<p:ajax event="select" update=":content" listener="#{menuController.setPage(node)}" />
<p:treeNode>
<h:outputText value="#{node}" />
</p:treeNode>
</p:tree>
</h:form>
</p:layoutUnit>
<p:layoutUnit position="east" size="50"/>
<p:layoutUnit position="south" size="60"/>
<p:layoutUnit position="center" id="centerlayout">
<h:panelGroup id="content">
<c:if test="${not empty menuController.page}">
<ui:include src="#{menuController.page}.xhtml" />
</c:if>
</h:panelGroup>
</p:layoutUnit>
</p:layout>
</h:body>
I would like to remark that I've tried to change the ui:include with EL and use the conditional render of a container h:panelGroup and an static ui:include, but the problem persist.
The backing bean of Tree menu:
#Named
#SessionScoped
public class MenuController implements Serializable {
private TreeNode root;
private TreeNode selectedNode;
private String pageName;
public MenuController() {
root = new DefaultTreeNode("Root", null);
TreeNode node0 = new DefaultTreeNode("Node 0", root);
TreeNode node00 = new DefaultTreeNode("/list", node0);
TreeNode node01 = new DefaultTreeNode("/list2", node0);
}
public TreeNode getRoot() {
return root;
}
public TreeNode getSelectedNode() {
return selectedNode;
}
public void setSelectedNode(TreeNode selectedNode) {
this.selectedNode = selectedNode;
}
public void setPage(String page){
this.pageName = page;
}
public String getPage(){
return this.pageName;
}
The page that contains data table list.xhtml (note that list2.xhtml is equal, changing some text to 'watch' the content update):
<ui:composition>
<h:form id="ItemListForm">
<p:panel header="Title">
<p:dataTable id="datalist" value="#{itemController.items}" var="item"
selectionMode="single" selection="#{itemController.selected}"
rowKey="#{item.itemid}"
paginator="true"
rows="10"
rowsPerPageTemplate="10,20,30" >
<p:column sortBy="#{item.itemid}" filterBy="#{item.itemid}">
<f:facet name="header">
<h:outputText value="Id"/>
</f:facet>
<h:outputText value="#{item.itemid}"/>
</p:column>
<p:column sortBy="#{item.productid}" filterBy="#{item.productid}">
<f:facet name="header">
<h:outputText value="ProductId"/>
</f:facet>
<h:outputText value="#{item.productid}"/>
</p:column>
<p:column sortBy="#{item.name}" filterBy="#{item.name}">
<f:facet name="header">
<h:outputText value="Name"/>
</f:facet>
<h:outputText value="#{item.name}"/>
</p:column>
<p:column sortBy="#{item.description}" filterBy="#{item.description}">
<f:facet name="header">
<h:outputText value="Description"/>
</f:facet>
<h:outputText value="#{item.description}"/>
</p:column>
</p:dataTable>
</p:panel>
</h:form>
The ItemController bean:
#Named
#SessionScoped
public class ItemController implements Serializable {
private Item selected;
private List<Item> items;
public ItemController() {
this.items = new ArrayList<>();
this.items.add(new Item("1", "1", "Product 1", "testing sorting"));
this.items.add(new Item("3", "3", "Product 3", "testing sorting"));
this.items.add(new Item("2", "2", "Product 2", "testing sorting"));
this.items.add(new Item("4", "4", "Product 4", "testing sorting"));
this.items.add(new Item("5", "5", "Product 5", "testing sorting"));
this.items.add(new Item("6", "6", "Product 6", "testing sorting"));
}
public Item getSelected() {
return selected;
}
public void setSelected(Item selected) {
this.selected = selected;
}
public List<Item> getItems() {
return items;
}
The class Item, very simple:
public class Item implements Serializable {
private String itemid;
private String productid;
private String name;
private String description;
public Item() {
}
public Item(String itemid) {
this.itemid = itemid;
}
public Item(String itemid, String productid, String name, String description) {
this.itemid = itemid;
this.productid = productid;
this.name = name;
this.description = description;
}
public String getItemid() {
return itemid;
}
public void setItemid(String itemid) {
this.itemid = itemid;
}
public String getProductid() {
return productid;
}
public void setProductid(String productid) {
this.productid = productid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
Finally, I'm working with:
Java EE 7
PrimeFaces 3.5 Community
JSF 2.2
Glassfish 4
NetBeans 7.3.1
Safari browser
the problem is taht Primefaces 3.5 doesnt go well with glassfish 4 switch to primefaces 4.0-SNAPSHOT and I guess it might work
I'm sorry, I speak english not well, but this happens because PF include to the page only javascript that needed for succesfully rendering of components that are present on the page. If you include component to the page dinamically by using for example ui:include, page will not contain js for rendering of this component

JSF ajax validation don't validate items with required true

I have a datatable, a column with h:commandlink for edit (ajax request), the detail show in jquery dialog, everything ok, in the edit form i have h:commandlink (ajax request) for save, if i make changes eg, drop a value in input required, and push submit, jsf don't validate this input, and don't show the message "this input is required"
<div id="container">
<button id="create-user" >Create new user</button>
<h:dataTable value="#{gasweb.lsProveedor}" var="tabpro" id="example" class="display dataTable" >
<h:column>
<f:facet name="id">
<h:outputLabel value="Id"/>
</f:facet>
<h:outputText value="#{tabpro.proveedor_id}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputLabel value="Cedula"/>
</f:facet>
<h:outputText value="#{tabpro.cedula_ruc}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputLabel value="NombreComercial"/>
</f:facet>
<h:commandLink value="#{tabpro.nombre_comercial}" actionListener="#{gasweb.doEditProveedor2}" class="labrir" >
<f:param name="pproveedor_id" value="#{tabpro.proveedor_id}" />
<f:ajax execute="#this" render=":forma:editgrid" >
</f:ajax>
</h:commandLink>
</h:column>
<h:column>
<f:facet name="header">
<h:outputLabel value="Razon Social"/>
</f:facet>
<h:outputText value="#{tabpro.razon_social}"/>
</h:column>
</h:dataTable>
</div>
<div id="divformap" title="Proveedor">
<h:inputHidden value="#{gasweb.newRecord}" id="txtnewrecord" />
<h:inputHidden value="#{gasweb.ruc_proveedor_ori}" id="txtcedulaori" />
<h:panelGrid columns="2" id="editgrid" >
<h:outputLabel value="Id :" />
<h:outputText id="txtid" value="#{gasweb.proveedor.proveedor_id}" />
<h:outputLabel value="Ruc :" />
<h:inputText id="txtcedula" value="#{gasweb.proveedor.cedula_ruc}" size="20" class="text ui-widget-content ui-corner-all" />
<h:outputLabel value="Nombr Comercial :" />
<h:inputText id="txtnombre" value="#{gasweb.proveedor.nombre_comercial}" required="true" size="80" class="text ui-widget-content ui-corner-all"/>
<h:outputLabel value="Razón Social :" />
<h:inputText id="txtrazon" value="#{gasweb.proveedor.razon_social}" size="80" class="text ui-widget-content ui-corner-all"/>
<h:outputLabel value="Dirección :" />
<h:inputText id="txtdireccion" value="#{gasweb.proveedor.direccion}" size="80" class="text ui-widget-content ui-corner-all"/>
<h:outputLabel value="Telefono :" />
<h:inputText id="txttelefono" value="#{gasweb.proveedor.telefono}" size="20" class="text ui-widget-content ui-corner-all"/>
<h:outputLabel value="Estado :" />
<h:outputText id="txtestado" value="#{gasweb.proveedor.estado}" />
<h:commandButton id="aceptar" value="Aceptar" actionListener="#{gasweb.doGrabaProveedor}" >
<f:param name="pproveedor_id2" value="#{gasweb.proveedor.proveedor_id}" />
<f:ajax render="bProveedor" execute="#form" onevent="resetFocus" />
</h:commandButton>
<h:outputText id="bProveedor" value="#{gasweb.bProveedorExiste}" />
</h:panelGrid>
</div>
My managed bean
public class GasperWebMB implements Serializable{
private List<Contribuyente> lsContribuyente;
private List<Proveedor> lsProveedor;
private Contribuyente contribuyente;
private Proveedor proveedor;
private Declara serdec;
private FacesContext fc = FacesContext.getCurrentInstance();
private Boolean newRecord;
private String ruc_proveedor_ori;
private String bProveedorExiste;
//#ManagedProperty("#param.pproveedor_id")
//private Integer pproveedor_id;
//private HttpServletRequest request;
public GasperWebMB(){
serdec = new Declara();
contribuyente = new Contribuyente();
proveedor = new Proveedor();
lsContribuyente = serdec.getAllContribuyente();
lsProveedor = serdec.getAllProveedor();
newRecord = true;
log("creado");
//request.getHeader(ruc_proveedor_ori);
}
public String getbProveedorExiste() {
return bProveedorExiste;
}
public void setbProveedorExiste(String bProveedorExiste) {
this.bProveedorExiste = bProveedorExiste;
}
public String getRuc_proveedor_ori() {
log(ruc_proveedor_ori);
return ruc_proveedor_ori;
}
public void setRuc_proveedor_ori(String ruc_proveedor_ori) {
log(ruc_proveedor_ori);
this.ruc_proveedor_ori = ruc_proveedor_ori;
}
public Boolean getNewRecord() {
log(newRecord);
return newRecord;
}
public void setNewRecord(Boolean newRecord) {
log(newRecord);
this.newRecord = newRecord;
}
public List<Proveedor> getLsProveedor() {
log(lsProveedor);
return lsProveedor;
}
public void setLsProveedor(List<Proveedor> lsProveedor) {
log(lsProveedor);
this.lsProveedor = lsProveedor;
}
public Proveedor getProveedor() {
log(proveedor);
return proveedor;
}
public void setProveedor(Proveedor proveedor) {
log(proveedor);
this.proveedor = proveedor;
}
public List<Contribuyente> getLsContribuyente() {
return lsContribuyente;
}
public void setLsContribuyente(List<Contribuyente> lsContribuyente) {
this.lsContribuyente = lsContribuyente;
}
public Contribuyente getContribuyente() {
return contribuyente;
}
public void setContribuyente(Contribuyente contribuyente) {
this.contribuyente = contribuyente;
}
public String doEditContribuyente(){
Map<String, String> params = fc.getExternalContext().getRequestParameterMap();
contribuyente = serdec.getContribuyenteById(Integer.parseInt(par));
newRecord = false;
ruc_proveedor_ori = proveedor.getCedula_ruc();
return "FContribuyente";
}
public String doGrabaContribuyente(){
System.out.println("grabar " + contribuyente.getCedula_ruc()+ " id " + contribuyente.getContribuyente_id());
serdec.updContribuyente(contribuyente);
return "lisContribuyente";
}
public String doEditProveedor(){
System.out.println("Entra");
Map<String, String> params = fc.getExternalContext().getRequestParameterMap();
String par = params.get("pproveedor_id");
System.out.println("pro" + par);
proveedor = serdec.getProveedorById(Integer.parseInt(par));
newRecord = false;
System.out.println("va a salir");
return "editprov";
}
public void doGrabaProveedor(ActionEvent event){
System.out.println("gra"+proveedor.getNombre_comercial()+" new "+ newRecord);
Proveedor xpro = serdec.getProveedorByRuc(proveedor.getCedula_ruc());
if (xpro != null && !proveedor.getCedula_ruc().equals(ruc_proveedor_ori)){
System.out.println("Ya existe");
bProveedorExiste = xpro.getNombre_comercial();
//FacesContext.getCurrentInstance().validationFailed();
FacesMessage fmes = new FacesMessage("El Ruc "+proveedor.getCedula_ruc()+" ya se encuentra registrado para otro proveedor");
fc.addMessage(null, fmes);
//fc.addMessage("Proveedor ya existe", fmes);
//return "sucess";
return;
}
if (newRecord){
proveedor.setEstado("A");
//serdec.insProveedor(proveedor);
}
else {
//serdec.updProveedor(proveedor);
}
System.out.println("Si graba");
//return "sucess";
}
public void doEditProveedor2(ActionEvent event){
/*Map<String, String> params = fc.getExternalContext().getRequestParameterMap();
String par = params.get("pproveedor_id");
proveedor = serdec.getProveedorById(Integer.parseInt(par));
newRecord = false;
return "FProveedor";*/
String pproveedor_id = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("pproveedor_id");
proveedor = serdec.getProveedorById(Integer.parseInt(pproveedor_id));
newRecord = false;
System.out.println("si edit2 param "+ pproveedor_id + " new "+ newRecord);
System.out.println("si edit2 proveedor "+ proveedor.getNombre_comercial() + " new "+ newRecord);
}
private void log(Object object) {
String methodName = Thread.currentThread().getStackTrace()[2].getMethodName();
System.out.println("Bean " + methodName + ": " + object);
}
}
In this code, dropped the jquery dialog and show detail in div
you must either put <h:messages /> or <h:message /> at html page.
h:messages – Output all messages in current page.
h:message – Output a single message for a specific component.
1- in your case, try put <h:messages /> at the top page or inside the edit form.
2- or u can to put <h:message /> for each required input such as
<h:message for="txtnombre" style="color:red" /> after/before the input.

Problems sorting a richfaces datatable

I'm trying to get my richfaces datatable to have sortable headers. I've basically followed the code here: http://richfaces-showcase.appspot.com/richfaces/component-sample.jsf?demo=dataTable&sample=tableSorting&skin=blueSky
My headers have links, and when I click them, you can see in the firebug console that a post request is happening. After it's done processing, nothing happens to the table.
Also, I have some jquery code that highlights a row when your mouse is hovered over it. Once you click one of the headers, the row highlighting doesn't happen anymore.
Here is my code.
<h:form>
<rich:dataTable value="#{protocolDetail.details.protocolEvents}" var="detail" id="table" rows="20" rowClasses="odd, even" styleClass="stable">
<rich:column sortBy="#{detail.date}">
<f:facet name="header">
<a4j:commandLink value="Date" render="table" action="#{protocolDetail.sortByDate}" />
</f:facet>
<f:facet name="footer">
<a4j:commandLink value="Date" render="table" action="#{protocolDetail.sortByDate}" />
</f:facet>
<h:outputText value="#{detail.date}" />
</rich:column>
<rich:column sortBy="#{detail.description}">
<f:facet name="header">
<a4j:commandLink value="Description" render="table" action="#{protocolDetail.sortByDescription}" />
</f:facet>
<f:facet name="footer">
<a4j:commandLink value="Description" render="table" action="#{protocolDetail.sortByDescription}" />
</f:facet>
<h:outputText value="#{detail.description}" />
</rich:column>
<rich:column sortBy="#{detail.comment}">
<f:facet name="header">
<a4j:commandLink value="Comment" render="table" action="#{protocolDetail.sortByComments}" />
</f:facet>
<f:facet name="footer">
<a4j:commandLink value="Comment" render="table" action="#{protocolDetail.sortByComments}" />
</f:facet>
<h:outputText value="#{detail.comment}" />
</rich:column>
</rich:dataTable>
</h:form>
<rich:jQuery selector=".stable tr" event="mouseover" query="jQuery(this).addClass('active')" />
<rich:jQuery selector=".stable tr" event="mouseout" query="jQuery(this).removeClass('active')" />
bean:
#ManagedBean(name = "protocolDetail")
#SessionScoped
public class ProtocolDetailBacker extends BaseObject {
private String protocol = "";
private int studyNumber;
// private ArrayList<ProtocolDetailBean> details;
private ProtocolDetailBean details = new ProtocolDetailBean();
ProtocolDAO dao = new ProtocolDAO();
private SortOrder dateOrder = SortOrder.UNSORTED;
private SortOrder descriptionOrder = SortOrder.UNSORTED;
private SortOrder commentsOrder = SortOrder.UNSORTED;
public ProtocolDetailBacker() {
FacesContext context = FacesContext.getCurrentInstance();
String[] values = context.getExternalContext().getRequestParameterValuesMap().get("protocol");
setProtocol(values[0]);
}
public String getProtocol() {
return protocol;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public ProtocolDetailBean getDetails() {
try {
studyNumber = dao.getStudyNumber(getProtocol());
details.setProtocolNumber(getProtocol());
details.setStudyChair(dao.getStudyChair(studyNumber));
details.setShortDesc(dao.getShortDescription(studyNumber));
details.setLongDesc(dao.getLongDescription(studyNumber));
details.setPdc(dao.getPDC(studyNumber));
details.setProtocolEvents(dao.getProtocolEventDetails(getProtocol()));
System.out.println("");
} catch (SQLException e) {
e.printStackTrace();
}
return details;
}
public void setDetails(ProtocolDetailBean details) {
this.details = details;
}
public int getStudyNumber() {
return studyNumber;
}
public void setStudyNumber(int studyNumber) {
this.studyNumber = studyNumber;
}
public SortOrder getDateOrder() {
return dateOrder;
}
public void setDateOrder(SortOrder dateOrder) {
this.dateOrder = dateOrder;
}
public SortOrder getDescriptionOrder() {
return descriptionOrder;
}
public void setDescriptionOrder(SortOrder descriptionOrder) {
this.descriptionOrder = descriptionOrder;
}
public SortOrder getCommentsOrder() {
return commentsOrder;
}
public void setCommentsOrder(SortOrder commentsOrder) {
this.commentsOrder = commentsOrder;
}
public void sortByDate() {
descriptionOrder = SortOrder.UNSORTED;
commentsOrder = SortOrder.UNSORTED;
System.out.println("dateOrder = "+dateOrder);
if(dateOrder.equals(SortOrder.ASCENDING)) {
setDateOrder(SortOrder.DESCENDING);
System.out.println("dateOrder now = "+dateOrder);
} else if(dateOrder.equals(SortOrder.DESCENDING)) {
setDateOrder(SortOrder.ASCENDING);
System.out.println("dateOrder now = "+dateOrder);
} else {
setDateOrder(SortOrder.ASCENDING);
System.out.println("else dateOrder now = "+dateOrder);
}
}
public void sortByDescription() {
dateOrder = SortOrder.UNSORTED;
commentsOrder = SortOrder.UNSORTED;
System.out.println("dateOrder = "+dateOrder);
if(descriptionOrder.equals(SortOrder.ASCENDING)) {
setDescriptionOrder(SortOrder.DESCENDING);
System.out.println("dateOrder now = "+dateOrder);
} else if(descriptionOrder.equals(SortOrder.DESCENDING)) {
setDescriptionOrder(SortOrder.ASCENDING);
System.out.println("dateOrder now = "+dateOrder);
} else {
setDescriptionOrder(SortOrder.ASCENDING);
System.out.println("else dateOrder now = "+dateOrder);
}
}
public void sortByComments() {
descriptionOrder = SortOrder.UNSORTED;
commentsOrder = SortOrder.UNSORTED;
System.out.println("dateOrder = "+dateOrder);
if(commentsOrder.equals(SortOrder.ASCENDING)) {
setCommentsOrder(SortOrder.DESCENDING);
System.out.println("dateOrder now = "+dateOrder);
} else if(commentsOrder.equals(SortOrder.DESCENDING)) {
setCommentsOrder(SortOrder.ASCENDING);
System.out.println("dateOrder now = "+dateOrder);
} else {
setCommentsOrder(SortOrder.ASCENDING);
System.out.println("else dateOrder now = "+dateOrder);
}
}
}
Sorting your table recreates the rows. Therefor the onmouseover and onmouseout events are no more bound to your rows after sorting.
Luckily jQuery can handle this by creating a live handler. Live-Handlers will also trigger to rows, that are added after the execution of the jQuery-call.
The following works for me:
<rich:jQuery selector=".stable tr" query="live('mouseover mouseout', function(event) {
if ( event.type == 'mouseover' ) {
jQuery(this).addClass('active-row');
} else {
jQuery(this).removeClass('active-row');
}});"/>
I too had the same problem was working with the sample code given in richfaces demo , still same issue
I added f:ajax to the a:commandlink now the sort is getting properly updated
<a4j:commandLink execute="#this" value="Vendor"
render="carstable" action="#{carsSortingBean.sort}">
<f:param name="sortProperty" value="vendor" />
<f:ajax render="carstable" />
</a4j:commandLink>
In case anyone is still looking for this answer, If you're using RichFaces 4.0 and JSF 2, try setting JSF's partial state saving to true in your web.xml as seen below:
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>true</param-value>
</context-param>

Resources