-
1. Re: (RichFaces ShowCase, rich:dataTable, Data Table Edit): Edition PopUp Panel holds old values
liuliu Feb 10, 2014 9:07 AM (in response to mekkimoh)It is because the modalpanel is in the same form of datatable. You need add execute="@this" on the commandbutton to fix this problem.
or put the modalpanel in another form.
-
2. Re: (RichFaces ShowCase, rich:dataTable, Data Table Edit): Edition PopUp Panel holds old values
mekkimoh Feb 10, 2014 10:33 AM (in response to liuliu)Hi Liumin,
First of all, thank you for your interest.
1 - Using two different forms
Before looking in the ShowCase i tried several configurations where two forms were used:
one for the dataTable and another one for the popupPanel, including settings where the second form
was containing or contained by the popupPanel, and none was working perfectly.
Could you provide some sample code working with different forms and providing the functionality described above,
i.e editing rows in a popupPanel ?
2 -
execute
=
"@this"
I also tried your suggestion to add
execute
=
"@this"
to the command button,presuming you were referring to the edition cancel commandButton.
Changing :
<
a4j:commandButton
value
=
"Cancel"
onclick
=
"#{rich:component('editPane')}.hide(); return false;"
/>
To
<
a4j:commandButton
execute
=
"@this"
value
=
"Cancel"
onclick
=
"#{rich:component('editPane')}.hide(); return false;"
/>
did not work. Values in the popupPanel are still outdated if a validation failure is triggered before.
The same trick did not work with the the edition confirmation commandButton (Store), worst: updates no longer work
if i change
execute
=
"editPane"
toexecute
=
"@this"
.3 - Further Googling the Problem
Meanwhile i further googled the problem and it seems to be a classical problem with Input Components.
See the community link below:
Validation and refresh problems...
Many solutions are proposed but they only apply to previous releases of RichFaces.
I am still trying to make these tricks work for Release 4, and i'll update this thread accordingly.
-
3. Re: (RichFaces ShowCase, rich:dataTable, Data Table Edit): Edition PopUp Panel holds old values
liuliu Feb 10, 2014 11:14 AM (in response to mekkimoh)sorry for my imprecision
1 you cant have nested form in jsf(html). so when use seperate form, you need remove domElementAttachment attribute on popuppanel, and form in the popuppanel.
2 execute="@this" to avoid the submit of the entire form that is why you fail on validation, so you should put on the action component, that means the edit commandlink.
-
4. Re: (RichFaces ShowCase, rich:dataTable, Data Table Edit): Edition PopUp Panel holds old values
mekkimoh Feb 10, 2014 6:36 PM (in response to liuliu)2 : Actually i really need that validation failure.
When the edition leaves data in an inconsistent state (typical example: required input left empty),
the user should be notified and invited to correct input.
Although when the user effectively corrects input and retries to store provided valid input things work perfectly.
Things go wrong when he decides instead to cancel the edition (so the edition popupPanel is closed leaving the form in an inconsistent validation status)
and chooses a different row to edit. In this case the edition popupPanel shows the old data.
Curiously only fields that were left empty in the first edition trial are updated with values from second row,
all other ones take the values of the first row.
Below you can see the commandLink that triggers the edition popupPanel:
<
a4j:commandLink
styleClass
=
"no-decor"
render
=
"editGrid"
execute
=
"@this"
oncomplete
=
"#{rich:component('editPane')}.show()"
>
<
h:graphicImage
value
=
"/images/icons/edit.gif"
alt
=
"edit"
/>
<
a4j:param
value
=
"#{it.index}"
assignTo
=
"#{carsBean.currentCarIndex}"
/>
<
f:setPropertyActionListener
target
=
"#{carsBean.editedCar}"
value
=
"#{car}"
/>
</
a4j:commandLink
>
You can first notice that the
execute
=
"@this"
is there.Then you can see that a f:setPropertyActionListener takes care of updating the carsBean.editedCar field,
which is used to fill input fields in the popupPanel with values of the selected row in the dataTable.
Curiously this update is not exhaustive since it only addresses fields that were left empty (null) in carsBean.editedCar.
The explanation i found for this is that JSF uses in priority submittedValue of the UIComponent to compute its final value
and not its bound value in the backing bean ... This explains why only inputs having null submittedValues are updated:
for them JSF went to the backing bean to get values.
I tried several tricks to nullify submittedValues for properties of carsBean.editedCar and thus force JSF
to get fresh values from the backing bean for all inputs without success.
Since problems come from validation errors (after that f:setPropertyActionListener behaves strangely) i was thinking about leveraging all constraints on inputs
(remove all required = "true" and use String for all fields even numerical ones) and handle validation by hand : close the popupPanel if input is correct,
or let it open and enrich with error messages for every input, i am pretty confident that this should work but it is somehow "dirty" coding ...
Sorry for the long explanation and i hope i correctly understood what you suggested.
1 : off course nested forms are not allowed ...
-
5. Re: (RichFaces ShowCase, rich:dataTable, Data Table Edit): Edition PopUp Panel holds old values
liuliu Feb 11, 2014 4:32 AM (in response to mekkimoh)hi,
I dont understand your problem. if you have a validation error, the update value phase should be skipped. If you want the user correct their input, dont close the popuppanel after save. if you want skip validation error, use execute="@this".
your need post your xhtml(datatable and popuppanel) and backingbean code.
by the way in jsf2, you can use the method with parameter in action of commandlink, it is easier than f:
setPropertyActionListener.
-
6. Re: Re: (RichFaces ShowCase, rich:dataTable, Data Table Edit): Edition PopUp Panel holds old values
mekkimoh Feb 11, 2014 8:56 AM (in response to liuliu)Hi again,
Here come Code Snippets.
More or less an adaptation of ShowCase:
XHTML Page
<?xml version="1.0" encoding="UTF-8"?> <!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:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:rich="http://richfaces.org/rich" xmlns:a4j="http://richfaces.org/a4j" > <h:head/> <h:body> <a4j:status onstart="#{rich:component('statutPanel')}.show()" onstop="#{rich:component('statutPanel')}.hide()" /> <h:form id="coffeesForm"> <center> <rich:dataTable id="listCoffeesRDT" value="#{coffeeBean.coffees}" var="coffee" iterationStatusVar="it" rows="3" rendered="true" > <f:facet name="header"> <h:outputText value="Coffee Shop" /> </f:facet> <rich:column> <f:facet name="header"> <h:outputText value="id" /> </f:facet> <h:outputText value="#{coffee.id}" /> </rich:column> <rich:column> <f:facet name="header"> <h:outputText value="name" /> </f:facet> <h:outputText value="#{coffee.name}" /> </rich:column> <rich:column> <f:facet name="header"> <h:outputText value="price" /> </f:facet> <h:outputText value="#{coffee.price}" /> </rich:column> <rich:column> <f:facet name="header" /> <a4j:commandLink execute="@this" render="@none" oncomplete="#{rich:component('deleteCoffeeConfirmationPanel')}.show()" > <h:graphicImage value="../resources/images/delete.gif" title="delete" alt="delete" /> <a4j:param value="#{it.index}" assignTo="#{coffeeBean.currentCoffeeIndex}" /> </a4j:commandLink> <a4j:commandLink render="editGrid" execute="@this" oncomplete="#{rich:component('editCoffeePanel')}.show()" > <h:graphicImage value="../resources/images/edit.gif" title="edit" alt="edit" /> <a4j:param value="#{it.index}" assignTo="#{coffeeBean.currentCoffeeIndex}" /> <f:setPropertyActionListener target="#{coffeeBean.coffee}" value="#{coffee}" /> </a4j:commandLink> </rich:column> <f:facet name="footer"> <rich:dataScroller id="listCoffeesRDS" page="#{coffeeBean.currentPage}" /> </f:facet> </rich:dataTable> <a4j:jsFunction name="deleteCoffee" action="#{coffeeBean.deleteCoffee}" render="listCoffeesRDT" execute="@this" oncomplete="#{rich:component('deleteCoffeeConfirmationPanel')}.hide();" /> <rich:popupPanel id="statusPanel" autosized="true" resizeable="false" > <h:graphicImage value="../resources/images/wait.gif" title="wait" alt="wait" /> Please wait ... </rich:popupPanel> <rich:popupPanel id="deleteCoffeeConfirmationPanel" autosized="true" resizeable="false" > Do you really want to delete Coffee Entry ? <a4j:commandButton value="cancel" onclick="#{rich:component('deleteCoffeeConfirmationPanel')}.hide(); return false;" /> <a4j:commandButton value="delete" onclick="deleteCoffee(); return false;" /> </rich:popupPanel> <rich:popupPanel id="editCoffeePanel" domElementAttachment="parent" autosized="true" resizeable="false" > <f:facet name="header"> <h:outputText value="Update Coffee" /> </f:facet> <h:panelGrid columns="3" id="editGrid" > <h:outputText styleClass="title-text" value="id" /> <h:outputText styleClass="data-text" value="#{coffeeBean.coffee.id}" /> <h:panelGroup /> <h:outputText styleClass="title-text" value="name" /> <h:inputText id="editCoffeeNameIn" value="#{coffeeBean.coffee.name}" maxlength="10" size="10" required="true" /> <rich:message for="editCoffeeNameIn" /> <h:outputText styleClass="title-text" value="price" /> <h:inputText id="editCoffeePriceIn" value="#{coffeeBean.coffee.price}" maxlength="6" size="6" required="true" /> <rich:message for="editCoffeePriceIn" /> </h:panelGrid> <a4j:commandButton value="update" action="#{coffeeBean.editCoffee}" render="listCoffeesRDT" execute="editCoffeePanel" oncomplete="if (#{facesContext.maximumSeverity==null}) {#{rich:component('editCoffeePanel')}.hide();}" /> <a4j:commandButton value="cancel" onclick="#{rich:component('editCoffeePanel')}.hide(); return false;" /> </rich:popupPanel> <h:commandLink value="Initialize" action="#{coffeeBean.init}" /> </center> </h:form> </h:body> </html>
CoffeeBean.java
import java.io.Serializable; import java.util.ArrayList; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Controller; @Controller @Scope("session") public class CoffeeBean implements Serializable { private static final long serialVersionUID = 1L; private ArrayList<Coffee> coffees; private Coffee coffee; private Integer currentCoffeeIndex; private Integer currentPage; // Getters/Setters ... @PostConstruct public void init() { clean(); } @PreDestroy public void clean() { setCoffees(new ArrayList<Coffee>()); getCoffees().add(new Coffee(1,"Arabica",11.99f)); getCoffees().add(new Coffee(2,"Robusta",12.99f)); getCoffees().add(new Coffee(3,"Liberia",13.99f)); getCoffees().add(new Coffee(4,"Skybury",14.99f)); setCoffee(null); setCurrentCoffeeIndex(null); setCurrentPage(null); } public void deleteCoffee() { getCoffees().remove(getCoffees().get(getCurrentCoffeeIndex())); } public void editCoffee() { getCoffees().set(getCurrentCoffeeIndex(), getCoffee()); } }
Coffee.java
import java.io.Serializable; public class Coffee implements Serializable { private static final long serialVersionUID = 1L; private Integer id; private String name; private Float price; // Getters/Setters ... public Coffee() { } public Coffee(Integer id, String name, Float price) { super(); this.id = id; this.name = name; this.price = price; } // Eclipse Generated equals/hashCode methods // involving id, name and price. }
Screenshots describing the problem:
1. Data Table with for each row delete and edit icons:
2. Click on edit icon of row with id = 1:
3. Leaving price field empty then click on update button, validation error message is displayed:
4. Click on Cancel, then click on edit icon of row with id = 2:
id is displayed correctly, but name and price come from previous canceled edit ...
REMARK: If in stead of leaving price field empty one leaves name field empty in step 3,
result in step 4. would be:
id : 2 (correct value)
name : Robusta (correct value)
price : 11.99 (wrong value)
Maybe somehow due to the special status of String objects in Java ?
-
7. Re: Re: (RichFaces ShowCase, rich:dataTable, Data Table Edit): Edition PopUp Panel holds old values
liuliu Feb 11, 2014 12:04 PM (in response to mekkimoh)could you show getCoffee of CoffeeBean? just simple getter?
if you continue edit the 3rd line, you have the same pb?
-
8. Re: Re: Re: (RichFaces ShowCase, rich:dataTable, Data Table Edit): Edition PopUp Panel holds old values
mekkimoh Feb 11, 2014 4:51 PM (in response to liuliu)1. Yes the getter is a regular one.
CoffeeBean.java (getters/setters):
public ArrayList<Coffee> getCoffees() { return coffees; } public void setCoffees(ArrayList<Coffee> coffees) { this.coffees = coffees; } public Coffee getCoffee() { return coffee; } public void setCoffee(Coffee coffee) { this.coffee = coffee; } public Integer getCurrentCoffeeIndex() { return currentCoffeeIndex; } public void setCurrentCoffeeIndex(Integer currentCoffeeIndex) { this.currentCoffeeIndex = currentCoffeeIndex; } public Integer getCurrentPage() { return currentPage; } public void setCurrentPage(Integer currentPage) { this.currentPage = currentPage; }
Coffee.java (getters/setters):
public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Float getPrice() { return price; } public void setPrice(Float price) { this.price = price; }
Something that looked strange to me: i added some display of coffeeBean.coffee
in the rich:popupPanel identified by "editCoffeePanel", its value was null all the time ...
Same thing if i display it outside the rich:popupPanel just before closing the form.
2. When i continue editing the 3rd row i encounter the same problem,
but i worked this out by transforming lines 170-173 of the XHTML page to:
<a4j:commandButton value="cancel" action="#{coffeeBean.cleanCoffee}" oncomplete="#{rich:component('editCoffeePanel')}.hide(); return false;" />
where cleanCoffee() method is (as expected) defined as follows:
public void cleanCoffee() { setCoffee(null); }
With those updates to the code, edition of third row becomes flawless:
So to summarize:
"edit + validation error + cancel" => "next edit is erroneous"
"edit + validation error + cancel + many(edit without validation error or simple cancel)" => "next edit is correct"
-
9. Re: (RichFaces ShowCase, rich:dataTable, Data Table Edit): Edition PopUp Panel holds old values
michpetrov Feb 12, 2014 10:59 AM (in response to mekkimoh)1 of 1 people found this helpfulThis is unfortunately a design choice of JSF (JSF-1060), after a validation error it won't rerender the input components, unless they are null.
-
10. Re: (RichFaces ShowCase, rich:dataTable, Data Table Edit): Edition PopUp Panel holds old values
mekkimoh Feb 12, 2014 11:44 AM (in response to michpetrov)Thanks Michal.
I've read to much about this, including here Validation and refresh problems... where people proposed indeed to nullify submitted values of Components before re-rendering and thus force JSF to take again values from the backing bean. It seems that solutions like here Re: Validation and refresh problems... was working with versions of RichFaces previous to 4. I tried to reuse the same idea with Version 4 (even if some classes are now missing) without success. I'll update the thread if things get better.
For now the quick and dirty solution would be to avoid JSF validation "police" by removing all constraints on input fields and handle by hand the validation ...
Or maybe a cleaner solution (with the risk of driving the user crazy) would be to remove the cancel button and leave the user with no way to close the modal popupPanel other than after a successful update ...