Cross Field Validation in JSF h:dataTable - java

I have a XHTML page in which there are four textboxes
<h:column >
<f:facet name="header">
<h:outputText value="Start Date" />
</f:facet>
<h:inputText id="startDate" value="#{sampleVO.startDate}" />
</h:column>
<h:column >
<f:facet name="header">
<h:outputText value="End Date" />
</f:facet>
<h:inputText id="endDate" value="#{sampleVO.endDate}" />
</h:column>
<h:column >
<f:facet name="header">
<h:outputText value="Start Date" />
</f:facet>
<h:inputText id="startDate1" value="#{sampleVO.startDate}" />
</h:column>
<h:column >
<f:facet name="header">
<h:outputText value="End Date" />
</f:facet>
<h:inputText id="endDate1" value="#{sampleVO.endDate}" />
</h:column>
I need to put a validation on Start Date and End Date. If user enters some Start and End date in id="startDate" & id="endDate" lets say Start Date: "01/01/2012" (1jan) and End Date: 01/31/2012 and if user enters some dates on id="startDate1" and id="endDate1" id="startDate1" should always be greater thn id="endDate" i.e date Ranges should not Overlap
public class SampleServiceimpl implements SampleService {
private List<SampleVO> listOfSample;
//this function gets called when clicked on Submit button on XHTML page
public Void submit() {
// how can i call datesOverLaps function to check entered
// start date and End date not overlapping, Also how to
// display the error message on XHTML page using FacingContext
}
public boolean datesOverlaps(List<SampleVO> sampleVO) {
final Date early = sampleVO.getStartDate();
final Date late = sampleVO.getEndDate();
for(SampleVO existing : sampleVO) {
if(!(early.isAfter(existing.getEnd())) ||
(late.isBefore(existing.getStart()))){
return true;
}
}
return false;
}
}
Not sure if the above boolean function is current and would work in the scenario.
Any help would be appreciated.

I spend 6 hours on this. But i solved it. My english is bad.
Add binding atribute on dataTable, pointing to UIDData field in backingbean (Bind table)
<h:dataTable value="#{narocilo.podatki}" id="tabela" var="podatek" border="0" bgcolor="#F6FAF0" style="width:100%;" cellspacing="0" cellpadding="2" headerClass="header" rowClasses="#{narocilo.rowClasses}" columnClasses="align_left,align_right,align_center,align_right,align_right,align_center_konec" **binding="#{narocilo.podatkiData}"**>
Before the end of form ad
<h:inputHidden id="validator" **validator="#{narocilo.validateKolicinaCena}"** value="morabiti"/>
validator method in backing bean
public void validateKolicinaCena(FacesContext aContext,UIComponent aComponent,Object aValue) {
int shrani_index = fPodatkiData.getRowIndex();
UIComponent column_kol = fPodatkiData.getChildren().get(2);
UIComponent column_cen = fPodatkiData.getChildren().get(5);
for(int i=0; i<fPodatkiData.getRowCount(); i++) {
fPodatkiData.setRowIndex(i);
UIInput kolicina_input = (UIInput) column_kol.findComponent("kolicina");
UIInput cena_input = (UIInput) column_cen.findComponent("cena");
Object kolicina = kolicina_input.getLocalValue();
Object cena = cena_input.getLocalValue();
if(kolicina == null && cena != null) {
kolicina_input.setValid(false);
FacesMessage sporocilo = Sporocila.getMessage("si.alkimisticus.bitea.error", "javax.faces.component.UIInput.REQUIRED", null);
sporocilo.setSeverity(FacesMessage.SEVERITY_ERROR);
aContext.addMessage(kolicina_input.getClientId(aContext), sporocilo);
} else if(kolicina != null && cena == null) {
cena_input.setValid(false);
FacesMessage sporocilo = Sporocila.getMessage("si.alkimisticus.bitea.error", "javax.faces.component.UIInput.REQUIRED", null);
sporocilo.setSeverity(FacesMessage.SEVERITY_ERROR);
aContext.addMessage(cena_input.getClientId(aContext), sporocilo);
} else {
kolicina_input.setValid(true);
cena_input.setValid(true);
}
}
fPodatkiData.setRowIndex(shrani_index);}

Related

Primefaces Datatable submits wrong data by Celledit

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"/>

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();
}

JSF <h:inputText> / <h:outputText> not rendering according to boolean value

I have a <h:dataTable> that is populated from an Entity class and displays different products. I want to be able to click a <h:commandLink> and edit row that the link belongs to. I have structured it mostly the same way as this nice example and article at mkyong.
The table (with some columns excluded):
<h:form>
<h:dataTable id="gnomeTable" value="#{gnome.productList}"
var="item"
styleClass="gnomeTable"
headerClass="gnomeTableHeader"
rowClasses="gnomeTableOddRow,gnomeTableEvenRow"
bgcolor="#F1F1F1" border="10" cellspacing="2"
rules="all" >
<f:facet name="header">
<h:outputText value="List of available gnomes for sale" />
</f:facet>
<h:column>
<f:facet name="header">
<h:outputText value="GnomeID" />
</f:facet>
<h:outputText value="#{item.id}"></h:outputText>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Name"/>
</f:facet>
<h:outputText value="#{item.name}" rendered="#{not item.editable}"></h:outputText>
<h:inputText value="#{item.name}" rendered="#{item.editable}"></h:inputText>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Available"/>
</f:facet>
<h:outputText value="#{item.available}" rendered="#{not item.editable}"></h:outputText>
<h:inputText value="#{item.available}" rendered="#{item.editable}"></h:inputText>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Edit"/>
</f:facet>
<h:commandLink value="Edit" action="#{gnome.editAction(item)}" rendered="#{not item.editable}" />
</h:column>
</h:dataTable>
<h:commandButton value="Save Changes" action="#{gnome.saveAction}" />
</h:form>
The Bean methods:
public String saveAction() {
for (Gnome g : productList) {
g.setEditable(false);
}
return null;
}
public String editAction(Gnome gnome) {
gnome.setEditable(true);
return null;
}
The property boolean editable in the entity class is annotated as #Transient since it's not a part of the persistant data and I don't want the entity manager to touch it:
#Transient
private boolean editable;
I thought this would result in the boolean variable being set to true when the Edit-button is clicked, the row re-renders with the fields now as <h:inputText>, but nothing happens. I have debugged it and made sure that the variable is set to true, which it is.
I also found this SO question that I thought perhaps could be something similar to the problem I am experiencing. The difference though is that a refresh of the page doesn't change anything.
What am I missing?
Edit 1:
In the first version of this question I had by mistake pasted the wrong code. The one that is included now is my current code, that in theory should work but does not.
Edit 2:
Initialization of productList, where Gnome is the entity class.
private List<Gnome> productList = new ArrayList<>();
public List<Gnome> getProductList() {
productList = gnomeFacade.findAll();
return productList;
}
public void setProductList(List<Gnome> productList) {
this.productList = productList;
}
After testing your example, the only possible error is that you are using a RequestScoped bean. In order to make it work, you need at least ViewScoped or SessionScoped. Ortherwise, the productList changed content is lost at every requests (button action).
According to the edit, the second mistake is how data is took. You need to load your data somewhere else than getter like this :
#PostConstruct
public void init()
{
productList = gnomeFacade.findAll();
}
public List<Gnome> getProductList()
{
return productList;
}
Ortherwise, at every actions your list is reset.

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