Primefaces Datatable submits wrong data by Celledit - java

I'm using Primefaces datatable with PF8.
Data is coming from ListDatamodel. I want to use Cell editing and implemented it exactly like shown in Primefaces showcase. After 3 or 4 inputs of new values, in the approriate bean the value gets updated, but with the old value. After a refresh of the page, the behaviour is normal again.
Here is the xhtml:
<p:dataTable style= "transform: scale(1); transform-origin: 0 0;" id="costingOverviewData" value="#{costingOverviewBean.model}" var="item"
editable="true" editMode="cell" selectionMode="single" disabledSelection="true"
rowStyleClass="#{(item.konto % 1000) eq 999 ? 'total':null}"
rowKey="#{item.ID}"
>
<p:ajax event="cellEdit" listener="#{costingOverviewBean.onCellEdit}" process="#this" />
<p:column rendered = "#{costingOverviewBean.showVorkalk ne false}" style="min-width: 20px;width:20px; max-width: 20px;">
<h:outputText value="#{item.konto}" />
</p:column>
<p:column style="min-width: 200px;width:200px; max-width: 200px;" >
<h:outputText value="#{item.beschreibung}" />
</p:column>
<p:column rendered = "#{costingOverviewBean.showVorkalk eq true}" width="75" headerText="#{res['COV_VorkalkQuantity']}" style="text-align:right">
<p:cellEditor>
<f:facet name="output">
<p:outputPanel style="#{item.menge_Vorkalk ne null ? 'border-style:solid;border-color:grey;border-width:0.5pt':'border-style:none'}">
<p:outputLabel value="#{item.menge_Vorkalk}">
<f:convertNumber integerOnly="true"></f:convertNumber>
</p:outputLabel>
</p:outputPanel>
</f:facet>
<f:facet name="input">
<p:inputNumber rendered="#{item.menge_Vorkalk ne null ? 'true':'false'}" id="menge_Vorkalk_Input" value="#{item.menge_Vorkalk}" style="width:96%">
</p:inputNumber>
</f:facet>
</p:cellEditor>
...
And here the bean:
public DataModel <KontenrahmenIstkosten> getModel() throws IOException {
if(model == null){
load_Strukturplan();
}
if (model == null){
model = new ListDataModel<KontenrahmenIstkosten>(list);
converter = new NumberConverter();
}
return this.model;
}
...
public void onCellEdit(CellEditEvent event) throws IOException {
System.out.println(event.getNewValue());
System.out.println(event.getRowKey());
init();
//PrimeFaces.current().ajax().update("form:pnlOfferEdit");
}
}
In extreme cases, I got also wrong data in fields which I never touched, and the whole table is messed up.
I'm struggling for 3 days now. Any help is appreciated!!
Edit: during value editing, getmodel() is called several times before calling of onCellEdit().
Is this normal behaviour? From my feeling, I face here a timing issue: Sometimes it is luckily working, sometimes not.

Did you try it without the process="#this"?
This only submits the values from the component.
<p:ajax event="cellEdit" listener="#{costingOverviewBean.onCellEdit}"/>
Or you can try adding the id instead of #this
<p:ajax event="cellEdit" listener="#{costingOverviewBean.onCellEdit}" process="costingOverviewData"/>

Related

The command button in dialog does not update the outputText with the id given

I have an outputText in a panelGrid which is also in a fieldset with the id of "foo". And I have a dialog. There is a datatable in this dialog and a commandbutton in the datatable. When I select an item of this datatable, and after clicking the commandbutton, I want the "foo" outputText's value to be changed with the data in the datatable in the dialog. But nothing seems to happen. I could use any help. Thanks in advance. Below is my xhtml snippet.
Edit: the method in the backing bean is also added to the post.
<!-- I want the "foo" to be updated with selected data in the dialog's datatable -->
<p:fieldset id="groupConfigurationPanel"
legend="#{messages['notificationGroup.title.NotificationGroupConfiguration']}"
styleClass="fieldSet">
<h:panelGrid columns="3"
columnClasses="formLayoutLabel, formLayoutInput, formLayoutValidator"
rowClasses="formLayoutOddRow, formLayoutEvenRow" cellpadding="0"
cellspacing="0" width="100%">
<h:outputText id="offerText" value="Offer" />
<h:outputText id="foo"
rendered="#{notificationGroupSupport.instance.offers!=null}" />
<p:commandButton value="Select Offer" id="selectOfferButton"
action="#{notificationGroupSupport.retrieveOfferList}"
type="submit" update=":selectOfferForm"
oncomplete="selectOfferVar.show();">
</p:commandButton>
</h:panelGrid>
</p:fieldset>
<!-- This is the dialog -->
<!-- This dialog has a datatable and the commandbutton in this datatable is supposed to update the outputText -->
<p:dialog id="offerDialog" header="Select Offer"
widgetVar="selectOfferVar" modal="true" resizable="true">
<h:form id="selectOfferForm">
<h:panelGrid columns="3" bgcolor="#eff5fa" cellspacing="5"
frame="box" styleClass="center">
<p:dataTable id="offerTable" var="offer" styleClass="dataList"
value="#{notificationGroupSupport.offerList}"
rowKey="#{offer.offerId}"
widgetVar="propertyTableVar" paginator="true" rows="12">
<f:facet name="header">
<div align="center">Offer List</div>
</f:facet>
<p:column selectionMode="single" style="width:18px" />
<p:column sortBy="#{offer.offerId}" headerText="ID"
filterBy="#{offer.offerId}" filterMatchMode="contains">
<h:outputText value="#{offer.offerId}" />
</p:column>
<p:column sortBy="#{offer.externalOfferId}"
headerText="External Offer Id"
filterBy="#{offer.externalOfferId}" filterMatchMode="contains">
<h:outputText value="#{offer.externalOfferId}" />
</p:column>
<p:column sortBy="#{offer.description}"
headerText="Description"
filterBy="#{offer.description}" filterMatchMode="contains">
<h:outputText value="#{offer.description}" />
</p:column>
<f:facet name="footer">
<p:commandButton value="Select" type="submit" id="nonajax"
actionListener="#{notificationGroupSupport.updateOffer()}"
styleClass="ui-priority-primary" ajax="false" update="foo"
oncomplete="propertyTableVar.hide();" />
</f:facet>
</p:dataTable>
</h:panelGrid>
</h:form>
</p:dialog>
// This is my method for this commandbutton's actionListener in my backing bean. I don't think this is an issue about my backing bean. The method called after select offer button got clicked
public void updateOffer()
{
campaignList = new ArrayList<Campaign>();
lifecyclePolicyList = new ArrayList<LifecyclePolicy>();
List<Offer> offers = getInstance().getOffers();
for (Offer offer : offers) {
if ( ( offer != null ) && ( offer.getOfferCampaignPairs() != null )
&& ( offer.getOfferCampaignPairs().size() > 0 ) ) {
for ( OfferCampaignPair pair : offer.getOfferCampaignPairs() ) {
campaignList.add( pair.getCampaign() );
if ( pair.getPrepaidLifecyclePolicy() != null ) {
lifecyclePolicyList.add( pair.getPrepaidLifecyclePolicy() );
}
if ( pair.getPostpaidLifecyclePolicy() != null ) {
lifecyclePolicyList.add( pair.getPostpaidLifecyclePolicy() );
}
}
} else if ( offer == null ) {
// todo
getInstance().setCampaigns( campaignList );
getInstance().setOffers( offerList );
getInstance().setLifeCyclePolicies( lifecyclePolicyList );
}
}
initConstants();
}

Changing assigned user using p:selectOneMenu

I have been searching for similar issue but I could not find any.
so here is the thing
I am trying to create a web application that deals with HR stuff, like employee requests (Resign, loan, vacation, etc..)
I am using primeface and I have the following problem that I cant figure out.
The thing is I am trying to do is :
1- When user first creates the request and assigns the user and submit the form
the next step is
2- the manager would sees the request and then change the "Person responsible for the request" to a new one using the drop menu in the datatable and I have been trying to solve this problem with no luck.
Here is the dialog script
<h:form id='resignf'>
<p:dialog id='res' header="Resign Request" widgetVar="resign" minHeight="40">
<p:outputLabel value="Employee name" />
<p:inputText value="#{controller.resignName}" required="true" requiredMessage="This field is required" />
<p:outputLabel value="Employee Number" />
<p:inputText value="#{controller.resignEmployeNum}" required="true" />
<p:inputText value="#{controller.resignNationalIDNum}" required="true" />
<p:inputText value="#{controller.resignNotes}" required="true" />
<p:outputLabel for="AssignUser" value="User" />
<p:selectOneMenu id="AssignUser" value="#{controller.assignUser}" style="width:150px" converter="UConverter">
<f:selectItems value="#{controller.usersList}" var="user" itemLabel="#{user.username}"/>
</p:selectOneMenu >
<p:commandButton action="#{controller.createResignRequest()}" onclick="PF('resign').hide();" update="#all"/>
</p:dialog>
And the code is my controller.java file below to create the request in the table
/* Request to resign*/
private List<ResignationRequest> resignList;
private ResignationRequestController rController = new ResignationRequestController();
private String resignName;
private String resignEmployeNum;
private String resignNationalIDNum;
private String ResignNotes;
private int AutoAssignToIDNUM;
/* end of request to resign*/
public void createResignRequest() {
System.out.println("createResignRequest");
ResignationRequest newResign = new ResignationRequest();
newResign.setName(resignName);
newResign.setEmployeeNum(resignEmployeNum);
newResign.setNationalID(resignNationalIDNum);
newResign.setNotes(ResignNotes);
newResign.setUserID(AssignUser);
rController.create(newResign);
resignList = rController.findResignationRequestEntities(); //retrieves all the resigns from the database
}
Now all that is working perfectly, but when I try to change the old user with the new one here I get confused! so far what I have been thinking is I need to find the old user and then switch him, but I could not figure a way to do it using the select list. The script for for changing the "User responsible for the request" below
<p:dataTable id="resignTable1" cellSeparator="true" editMode="cell" editable="true" var="resign" value="#{controller.resignList}" paginator="true" rows="10" rowIndexVar="index1">
<p:ajax id="aj" event="cellEdit" listener="#{controller.editUser(user)}" update="resignTable1"/>
<p:column headerText="Employee number">
<p:cellEditor>
<f:facet name="output"> <h:outputText value="#{resign.employeeNum}" /></f:facet>
<f:facet name="input"> <h:inputText value="#{resign.employeeNum}" /></f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="name">
<p:cellEditor>
<f:facet name="output"> <h:outputText value="#{resign.name}" /></f:facet>
<f:facet name="input"> <h:inputText value="#{resign.name}" /></f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Request Number">
<p:cellEditor>
<f:facet name="output"> <h:outputText value="#{resign.id}" /></f:facet>
<f:facet name="input"> <h:inputText value="#{resign.id}" /></f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="User responsible for the request">
<p:cellEditor>
<f:facet name="output"> <h:outputText value="#{resign.userID}" /></f:facet>
<f:facet name="input"> <h:inputText value="#{resign.userID}" /></f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Comments">
<p:cellEditor>
<f:facet name="output"> <h:outputText value="#{resign.notes}" /></f:facet>
<f:facet name="input"> <h:inputText value="#{resign.notes}" /></f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Send the request to the next employee">
<p:selectOneMenu id="AssignUser" value="#{controller.assignUser}" style="width:150px" converter="UConverter" onchange="submit();">
<f:selectItems value="#{controller.usersList}" var="user" itemLabel="#{user.username}" actionListener="#{controller.editRequestStep(resign)}" >
</f:selectItems>
</p:selectOneMenu >
In my controller file
public void editRequestStep(ResignationRequest r) {
System.out.println("Edit resign");
try {
System.out.println("Edit resign");
rController.edit(r);
} catch (Exception ex) {
Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex);
}
}
I tried to get as much as I could from the code but I have a lot of stuff that I am not sure if I should submit. I tried ajax
NOTE: I am using mySQL, apache tomcat in case if it matters.
Solved it.
public void editRequestStep(ResignationRequest r) {
System.out.println("Edit resign " + EditAssignUser +" this is userthig" + r.getName());
try {
System.out.println("Edit resign");
r.setUserID(EditAssignUser);
} catch (Exception ex) {
Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex);
}
}
<p:selectOneMenu id="AssignUser" value="#{controller.editAssignUser}" style="width:150px" converter="UConverter">
<p:ajax listener="#{controller.editRequestStep(resign)}" update="#all"/>
<f:selectItems value="#{controller.usersList}" var="user" itemLabel="#{user.username}" >
</f:selectItems>
I did not notice that I used the variable assignUser 2 times, which actually missed me up. So what I did is I created new Users variable called "editAssignUser" then in my controller I just set the user look at the code below
public void editRequestStep(ResignationRequest r) {
System.out.println("Edit resign " + EditAssignUser +" this is userthig" + r.getName());
try {
System.out.println("Edit resign");
r.setUserID(EditAssignUser);
} catch (Exception ex) {
Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex);
}
}

javax.el.ELException: java.lang.NullPointerException

I use primefaces single row selection data table , and i want to change a value on the selected row so this is my xhtml page
<h:form id="form">
<p:panel header="Prix des matériaux " style="width : 664px; " >
<br />
<p:dataTable id="cars" var="car" value="#{materielbean.listitemsmaterielBean}"
rowKey="#{car.iditemsmateriel}" paginator="true" rows="20"
selection="#{materielbean.selecteditemforprix}" selectionMode="single" >
<p:ajax event="rowSelect" update=":form:dialog" oncomplete="PF('carDialog').show()"/>
<f:facet name="header">
Liste de de matériel
</f:facet>
<p:column headerText="Désignation" filterBy="designation" >
#{car.designation}
</p:column>
<p:column headerText="Unité">
#{car.unite}
</p:column>
<p:column headerText="Prix en DT" >
#{car.prix}
</p:column>
</p:dataTable>
<p:dialog id="dialog" header="Changer le prix d'un article" widgetVar="carDialog"
resizable="true" showEffect="fade" hideEffect="explode">
<h:panelGrid columns="3">
<h:outputText value=" #{materielbean.selecteditemforprix.designation}" />
<p:inputText value="#{materielbean.selecteditemforprix.prix}"/>
<p:commandButton value="OK" action="#{materielbean.modifprixofitem()}"
onclick="PF('carDialog').hide()" update=":form:cars" />
</h:panelGrid>
</p:dialog>
</p:panel>
</h:form>
And this is the backing bean to modify the selected object
#ManagedBean(name="materielBean")
#SessionScoped
private ItemsMateriel selecteditemforprix;
public ItemsMateriel getSelecteditemforprix() {
return selecteditemforprix;
}
public void setSelecteditemforprix(ItemsMateriel selecteditemforprix) {
this.selecteditemforprix = selecteditemforprix;
}
public void modifprixofitem() {
itemmaterielDAO.Modifitemsmateriel(selecteditemforprix );
selecteditemforprix = new ItemsMateriel();
}
When I click "OK" I take the new value from the inputtext, update my object in the database and finally I update the data table, but when I did it like that, I got an error which says
22:16:48,999 GRAVE [javax.enterprise.resource.webcontainer.jsf.context] (http-localhost-127.0.0.1-8383-6) javax.el.ELException: /Gestionstock/Materiel/Matos.xhtml #28,97 rowKey="#{car.iditemsmateriel}": java.lang.NullPointerException
Well the problem is in the last lign selecteditemforprix = new ItemsMateriel(); i don't really know what's the problem with that lign but when i deleted it everything works fine, any other clarifications will be appreciated .

JSF - How to get old and new value when using Primefaces RowEditEvent?

I have a datatable with 2 columns(name and description) and I want to update my database when a person updates a row and clicks the checkmark which triggers the execBacking.update method.
In this method, I get the new values by casting event.getObject(), but how can i also get the old values? The name is my primary key so i need the old value to know which row to update in the db.
xhtml page
<p:ajax event="rowEdit" listener="#{execBacking.update}" update=":execForm:execMessages" />
<p:column headerText="Name">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{exec.name}" />
</f:facet>
<f:facet name="input">
<h:inputText value="#{exec.name}" />
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Description">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{exec.description}" />
</f:facet>
<f:facet name="input">
<h:inputText value="#{exec.description}" />
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Actions">
<p:rowEditor />
<p:commandLink styleClass="ui-icon ui-icon-trash" type="submit" actionListener="#{execBacking.delete}" update=":execForm:execMessages" >
<f:attribute name="execName" value="#{exec.name}" />
</p:commandLink>
</p:column>
</p:dataTable>
Backing bean
public void update(RowEditEvent event) {
Dao dao = new Dao(ds);
Exec exec = (Exec) event.getObject();
System.out.println("name = "+exec.getName()); //New name
System.out.println("desc = "+exec.getDescription()); //New desc
try {
// If the new exec was updated successfully
if(dao.updateExec(accessBacking.getUsername(), null, exec.getName(), exec.getDescription())) {
FacesContext.getCurrentInstance().addMessage("growl", new FacesMessage(FacesMessage.SEVERITY_INFO, "Success", "Exec Updated Successfully!"));
} else {
FacesContext.getCurrentInstance().addMessage("messages", new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error", "Error Updating Exec!"));
}
} catch (Exception e) {
FacesContext.getCurrentInstance().addMessage("messages", new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error", e.getMessage()));
}
}
I would recommend not having name be your primary key, but instead add an auto-incrementing id field and make that your primary key, and don't make that field editable by the user. This guarantees you always have access to the record that you want to update.
Generally speaking it's bad practice to attempt to modify the primary key in a database the way you're trying to do it.
You can register a ValueChangeListener on the component you're interested in using:
<p:column headerText="Description">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{exec.name}" />
</f:facet>
<f:facet name="input">
<h:inputText value="#{exec.name}">
<f:valueChangeListener binding="#{keyChangedListener}"/>
<f:ajax/>
</h:inputText>
</f:facet>
</p:cellEditor>
</p:column>
keyChangeListener will correspond to an implementation of ValueChangeListener and we're using <f:ajax/> here to ensure that the valueChanged event is fired on the textbox. Otherwise the listener will not be notified. Your listener should look something like:
#ManagedBean(name="keyChangedListener")
#ViewScoped
public class KeyChangeListener implements ValueChangeListener{
public void processValueChange(ValueChangeEvent event) throws AbortProcessingException{
Object oldValue = event.getOldValue(); //get the old value
Object newValue = event.getNewValue(); //get the new value
}
I'm using the #ViewScopedhere as advised by the JSF Spec, to avoid unwanted side effects.

JSF / Primefaces dataTable and sorting issue

I am using PrimeFaces 2.2, with JSF 2.0.3.
I have an xhtml view that contains the following datatable:
<p:dataTable id="fooTable"
widgetVar="fooTable"
rowKey="#{foo.id}"
var="foo"
value="#{fooQueue.foos}"
styleClass="table"
selection="#{fooQueue.selectedfoo}"
filteredValue="#{fooQueue.filteredfoos}"
paginatorPosition="bottom"
paginatorAlwaysVisible="true"
selectionMode="single"
rowEditListener="#{fooQueue.save}"
paginator="true"
rows="10"
rowIndexVar="#{foo.id}"
emptyMessage="No foos found with given criteria"
rowStyleClass="#{foo.status == const.submitted ? 'gray' : null}"
onRowSelectUpdate=":form:deleteValidation">
<p:column id="mothersName" filterBy="#{foo.header1}" filterMatchMode="contains">
<f:facet name="header">
<h:outputText value="Mother's Name" styleClass="tableHeader2" />
</f:facet>
<p:commandLink action="#{fooQueue.next(foo)}"
ajax="false"
disabled="#{foo.status == const.submitted || foo.id == 0}">
<f:setPropertyActionListener value="#{foo}" target="#{fooQueue.selectedfoo}" />
<h:outputText value="#{foo.header1}" styleClass="tableData" />
</p:commandLink>
</p:column>
<p:column sortBy="#{foo.header4}" >
<f:facet name="header">
<h:outputText value="DOB" styleClass="tableHeader2" style="width: 400px" />
</f:facet>
<h:outputText value="#{foo.header4}" styleClass="#{(foo.overSevenDays and foo.status != const.submitted and foo.id != 0)?'tableDataRed':'tableData'}" />
</p:column></p:dataTable>
.. with the following backing bean:
#ViewScoped
#ManagedBean
public class FooQueue extends BaseViewBean {
private List foos;
private Foo selectedFoo;
private List filterdFoos;
public FooQueue() {
logger.debug("Creating new FooRegQueue");
retrieveFooRecords();
}
private void retrieveFooRecords(){
foos = new ArrayList();
foos.addAll(fooService.getAllFoos());
}
public String next(Foo clickedFoo) {
System.out.println(clickedFoo.getId());
return "";
}
public Collection getFoos() {
return foos;
}
public Foo getSelectedFoo() {
return selectedFoo;
}
public void setSelectedFoo(Foo foo) {
if (foo != null) {
this.selectedFoo = foo;
}
}
public void setFilterdFoos(List filterdFoos) {
this.filterdFoos = filterdFoos;
}
public List getFilterdFoos() {
return filterdFoos;
}
}
Note the "commandLink" on the mother's name column, and the "sortBy" on the DOB column.
I've encountered a strange issue, which seems to be limited to IE, where if I sort the data by DOB, then paginate to the last page and click the commandLink of the last record in the table, it fires two action events. The first event correctly reports that I clicked on the last record in the sorted table. But the second invocation of the next() method is for the last record in the UNsorted table.
Can anyone identify anything wrong with my xhtml, or backing bean? Is this a known PrimeFaces issue? A known IE issue?
I am testing with IE 8.
I solved it. I simply had to change this:
<p:commandLink action="#{fooQueue.next(foo)}"
ajax="false"
disabled="#{foo.status == const.submitted || foo.id == 0}">
<f:setPropertyActionListener value="#{foo}" target="#{fooQueue.selectedfoo}" />
<h:outputText value="#{foo.header1}" styleClass="tableData" />
</p:commandLink>
to this:
<p:commandLink action="#{fooQueue.next(foo)}"
ajax="true"
disabled="#{foo.status == const.submitted || foo.id == 0}">
<f:setPropertyActionListener value="#{foo}" target="#{fooQueue.selectedfoo}" />
<h:outputText value="#{foo.header1}" styleClass="tableData" />
</p:commandLink>
Note the ajax="true". Because it was previously set to ajax="false", it was instantiating a new instance of my backing bean, and the row that was selected in the default sort order was being loaded. Now it does not instantiate a new instance, and I load the actual record I clicked on.

Categories