Primefaces - update not getting triggered while hiding the dialog - jsf

I have created a simplified version of my app below.
<h:form>
<p:commandButton value="ADD NEW" action="#{sampleBean.onAddNew}" oncomplete="PF('addDialog').show()" update=":addForm"/>
</h:form>
The below dialog opens when the button is clicked.
<p:dialog widgetVar="addDialog">
<h:form id="addForm">
<p:messages autoUpdate="true" closable="true"/>
<p:outputLabel value="Name :"/>
<p:inputText value="#{sampleBean.name}" required="true" requiredMessage="Name is a required field"/>
<p:outputLabel value="Address :"/>
<p:inputText value="#{sampleBean.address}"/>
<p:commandButton value="Save" action="#{sampleBean.save}" oncomplete="if (args && !args.validationFailed) PF('addDialog').hide();"/>
<p:commandButton value="Cancel" action="#{sampleBean.cancel}" immediate="true" oncomplete="PF('addDialog').hide()" update="addForm"/>
</h:form>
</p:dialog>
Here is the backing bean code:
public void onAddNew()
{
name = "";
address = "";
}
public void save()
{
System.out.println("Saving ... " + name + " : " + address);
name = "";
address = "";
}
public void cancel()
{
System.out.println("Cancelling ... " + name + " : " + address);
name = "";
address = "";
}
The problem i'm facing is:
If i encounter a required field validation error on name field and if address is entered and after that if i hit cancel, i'm invoking the action method "sampleBean.cancel"(to reset both name and address to blank) and then updating the form before hiding the dialog box.
However after hiding the dialog and if i click on ADD NEW again, Its still holding the old state(address value what i entered before).
My need is to clear and display the dialog without any old values.
Could someone point out the issue in my above code?
I'm using Primefaces 5.0
Found one solution to address it however i'm not sure if that's the right way to fix.
<p:commandButton value="Cancel" action="#{sampleBean.cancel}" immediate="true" oncomplete="PF('addDialog').hide()" update="addForm">
<p:resetInput target="addForm"/>
</p:commandButton>
Regards.

We have a similar dialog cancel button build up like this:
<p:commandButton value="#{bundle['common.action.cancel']}"
icon="#{bundle['common.icon.cancel']}"
action="#{bean.cancel}"
process="#this"
update="#none"
oncomplete="PF('dialog').hide();"/>
Where bean.cancel sets the dialog input values to null so we neither need further process nor update of other input elements.

Related

Each row in DataTable has checkboxes .How to uncheck the previous checked box, on check of new checkbox

On click of Add button, empty row with text box and check box is created. I have to enter the details in text box but only one checkbox should be checked. Now I can check all the check boxes. But if one is checked, other check boxes should be unchecked.
<p:commandButton value="Add"
actionListener="#{createReturns.addReturnBodyToList}" ajax="true"
update="bodyTable messages" style="margin-bottom:10px;"/>
<p:dataTable id="bodyTable" value="#{createReturns.returnBodyList}"
var="returnBody">
<p:column headerText="Element Name" style="width:250px;">
<p:inputText id="elementName" value="#{returnBody.elementName}"
style="width:240px;" />
</p:column>
<p:column headerText="KeyColumn" style="width:80px">
<p:selectBooleanCheckbox value="#{returnBody.keyColumn}" id="key">
<p:ajax listener="#{createReturns.toggleCheckBox()}"
event="click" update="key">
<f:attribute name="element" value="#{returnBody.elementName}"></f:attribute>
</p:ajax>
</p:selectBooleanCheckbox>
</p:column>
</p:datatable>
actionlistener for command button to add empty rows in datatable
public void addReturnBodyToList() {
returnBody = new ReturnBody();
returnBodyList.add(returnBody);
}
ajax listener to uncheck other check boxes in bean
public void toggleCheckBox(ActionEvent actionEvent) {
String elementName = (String) actionEvent.getComponent()
.getAttributes().get("element");
for (ReturnBody body : returnBodyList) {
if (!body.getElementName().equals(elementName))
body.setKeyColumn(false);
System.out.println("Check ajax: " + body.toString());
}
}
You can achieve this in your toggleCheckBox() method.
boolean flag; //Global
String lastChecked=new String();//global
if(!flag){
setFlag(true);
lastChecked=elementName;
}
if(flag){
for (ReturnBody body : returnBodyList) {
if (body.getElementName().equals(lastChecked)){
body.setKeyColumn(false);
lastChecked=elementName;
}
}
}

Ajax not function on first submit, after page refresh only result will refresh

I am using Java EJB with JSF.
What I doing is just a simple search result from database and display it on a table using JSF with ajax. But why when first submitting, the result is not appear. And second time only the result will appear.
Below is my JSF page code
<h:form id="wholeForm">
<p:panelGrid id="resultTable" styleClass="result_table1" >
<p:row>
<p:column>
<div align="center" id="font-size1">
<h:selectOneRadio value="#{scanResult.typeOfScan}">
<f:selectItem itemValue="Carrier" itemLabel="Carrier"></f:selectItem>
<f:selectItem itemValue="Slot" itemLabel="Slot"></f:selectItem>
<f:selectItem itemValue="HD" itemLabel="HD"></f:selectItem>
<p:ajax event="change"></p:ajax>
</h:selectOneRadio>
Scan: <p:inputText styleClass="searchField" id="counter" value="#{scanResult.serialNumber}" a:autofocus="true">
<p:ajax event="keydown" update="wholeForm" onstart="if (event.keyCode != 13) { return false;}" listener="#{scanResult.checkResult()}" />
</p:inputText>
<br/><br/>
</div>
</p:column>
</p:row>
</p:panelGrid>
<p:panelGrid id="resultTable1" styleClass="result_table1" rendered="#{not empty scanResult.scanResultCarrier}" >
<c:forEach items="#{scanResult.scanResultCarrier}" var="result" >
<!-- ..do something and call out result -->
</p:column>
</p:row>
</c:forEach>
</p:panelGrid>
</h:form>
And my managed bean is as below
#Named(value = "scanResult")
#SessionScoped
public class scanResult implements Serializable {
//Some code here
public void checkResult() {
scanResultCarrier = new ArrayList<>();
scanResultSlot = new ArrayList<>();
System.out.println("checking");
if (typeOfScan.equals("Carrier")) {
System.out.println("Serial " + serialNumber);
scanResultCarrier = scanresultcarrierFacade.searchResultCarrier(serialNumber);
System.out.println(scanResultCarrier.size());
} else if (typeOfScan.equals("Slot")) {
scanResultSlot = scanresultslotFacade.searchResultSlot(serialNumber);
} else if (typeOfScan.equals("HD")) {
} else {
}
serialNumber = "";
}
}
I use System.out.println(lsitofresult.size()); to print out my result and the result is not blank. Mean that I successful retrieve my result from database.
But my result table not able to show out after I click on enter.
Then I notice that my url is as below
http://localhost:8080/outgoingScanSystem-war/faces/index.xhtml;jsessionid=8b6cefa932ff60984607ee38ec13
And after I refresh my page, the result will appear again.
And my url change to :
http://localhost:8080/outgoingScanSystem-war/faces/index.xhtml
May I know why? Is it related to URL? I have no idea where should I start my troubleshoot. Anyone can give me some guideline?
I see some problems here. First of all, you're using the session scope while your managed bean should be view scoped (there's no reason to use the session here, see the link below). That's the cause why your results are getting displayed when you refresh the page.
Second, I'd rather put the search results out from the form. I see no reason for them to be in the same form of the search itself. Then, when performing a searh you should only update the result list:
<p:ajax event="keydown" update="resultTable1" onstart="if (event.keyCode != 13) { return false;}" listener="#{scanResult.checkResult()}" />
Third, as you're using Primefaces, I encourage you to take a look to its p:remoteCommand tool in order to perform ajax-based calls to the beans from your JS code directly. This way you should avoid your second problem, which seems to be that you're preventing the standard form sending on the ajax start event (which might not even get called). You could do something like this:
<p:remoteCommand name="search" update="resultTable1" actionListener="#{scanResult.checkResult}" />
<p:inputText styleClass="searchField" id="counter" value="#{scanResult.serialNumber}"
a:autofocus="true" onkeypress="if (event.keyCode != 13) {search(); return false;}">
<!-- Update the input text value in the bean for each pressed key -->
<p:ajax event="keydown" />
</p:inputText>
See also:
How to choose the right bean scope?
Jsf calling bean method from input text when pressing enter

Hiding a JSF Label Based on condition..!

I have JSF text box like this
<p:outputLabel value="#{msgs['label.responsible']}:" for="printingResponsibleEdit"
rendered="#{b2cOrderDetailBean.b2cActionOrderView.canChangePrintingInfo() and
b2cOrderDetailBean.b2cActionOrderView.showExecutionInfo}" />
<h:panelGroup id="printresponsible"
rendered="#{b2cOrderDetailBean.b2cActionOrderView.canChangePrintingInfo() and
b2cOrderDetailBean.b2cActionOrderView.showExecutionInfo}">
<p:inputText id="printingResponsibleEdit" value="#{b2cOrderDetailBean.b2cActionOrderView.printingResponsiblePersNr}" size="4"
valueChangeListener="#{b2cOrderDetailBean.changeListenerString}" required="true" immediate="true"
requiredMessage="#{msgs['msg.required']}" binding="#{printingResponsibleBinding}" maxlength="4">
<f:attribute name="historyTypeCode" value="PR" />
</p:inputText>
<h:outputText value=" " />
<p:commandButton value="#{msgs['button.ok']}" immediate="true" process="printingResponsibleEdit"
actionListener="#{b2cOrderDetailBean.requestPrintingResponsible}" escape="false"
update="printingResponsibleName printingResponsibleEditMsg">
<f:attribute name="printingResponsible" value="#{printingResponsibleBinding.localValue}" />
<f:param name="responsiblePersonName" value="#{b2cOrderDetailBean.b2cActionOrderView.printingResponsiblePersNr}"></f:param>
</p:commandButton>
<h:outputText id="printingResponsibleName" value=" #{b2cOrderDetailBean.b2cActionOrderView.printingResponsible}" />
</h:panelGroup>
<p:message id="printingResponsibleEditMsg" for="printingResponsibleEdit" />
And i have my managed beans method like this
public void requestPrintingResponsible(ActionEvent actionEvent) {
try {
b2cActionOrderView.setPrintingResponsible(null);
b2cActionOrderView.setPrintingResponsibleName(null);
b2cActionOrderView.setPrintingResponsiblePersNr(null);
String persNr = (String) actionEvent.getComponent().getAttributes().get("printingResponsible");
if (persNr != null) {
Account account = accountDelegate.findByPersNr(persNr, localeView.getLocale());
b2cActionOrderView.setPrintingResponsible(account.getAccountId());
b2cActionOrderView.setPrintingResponsibleName(account.getName());
b2cActionOrderView.setPrintingResponsiblePersNr(account.getPersNr());
validatedPrintingResponsible = account.getPersNr();
} else {
b2cActionOrderView.setPrintingResponsible(null);
}
} catch (NoDataFoundException e) {
LOG.warn("PersNr not found.", e);
b2cActionOrderView.setPrintingResponsible(null);
b2cActionOrderView.setPrintingResponsibleName(null);
b2cActionOrderView.setPrintingResponsiblePersNr(null);
MessageUtil.addFacesMessage("msg.notFound", colruyt.giftactionmgmt.util.Constants.MSG_PACKAGE, FacesMessage.SEVERITY_ERROR,
false, "form:tabView:printingResponsibleEdit", null);
}
}
My problem is when i enter a value that is there in the db and after that if i press ok button the corrensponding user name and user id is displayed but after that if i clear the value in the text box and if i press ok button must be filled error message is coming but the previous lable is not getting cleared.
ie(username,user id).
I have tried in many ways to achieve this can you guys help me
Your problem is clear immediate="true"
When you put immediate="true" on your commandButton you simply say to JSF please skip any validation on form (including printingResponsibleEdit) and process this action (requestPrintingResponsible)
So how can JSF validate printingResponsibleEdit and render an updated p:message(printingResponsibleEditMsg) if you have already skipped the validation phase , See More on JSF lifecycle
Put on your mind you have to render(update) every single component you want it to be updated after Ok button is pressed or simply you can make h:panelGroup container to your component and give it an ID and update it ex: <p:commandButton ... update='containerId'/>.

Creating master-detail table and dialog, how to reuse same dialog for create and edit

I am attempting to create a dialog that will serve the purpose of both creating objects and updating them. So if I happen to click the 'new' button I will be presented a dialog containing empty fields to be filled or if I click on an edit button for an entry, that entry's data will presented in the dialog for update.
Following the example in the primefaces showcase for version 5.2, I can present the data in a read only outputText form, however when I change it to an inputText, the field remains empty. The following code is an example of what I have:
<h:form id="form">
<p:dataGrid id="guestList" var="guest" value="${guestList.guests}" columns="3" paginator="true" rows="20">
<f:facet name="header">
Guest List
</f:facet>
<p:panel>
<h:outputText value="${guest.name}" />
<br />
<h:outputText value="${guest.street}" />
<br />
<h:outputText rendered="#{guest.street2.length() gt 0}"
value="${guest.street2}" />
<h:panelGroup rendered="#{guest.street2.length() gt 0}">
<br />
</h:panelGroup>
<h:outputText value="${guest.city}, " />
<h:outputText value="${guest.state} " />
<h:outputText value="${guest.zipCode}" />
<p:commandButton update="#form:newGuestDetail" oncomplete="PF('newGuestDialog').show()" icon="ui-icon-edit" styleClass="ui-btn-inline">
<h:outputText styleClass="ui-icon ui-icon-edit" style="margin:0 auto;" />
<f:setPropertyActionListener value="#{guest}" target="#{guestList.selectedGuest}" />
</p:commandButton>
</p:panel>
</p:dataGrid>
<p:dialog header="#{guestList.hasSelected() ? 'Edit Guest' : 'New Guest'}" widgetVar="newGuestDialog" modal="true" showEffect="fade" hideEffect="fade">
<p:outputPanel id="newGuestDetail">
<h:outputText value="'#{guestList.selectedGuest.name}'"/>
<p:inputText id="guestName" value="#{guestList.hasSelected() ? '' : guestList.selectedGuest.name}" pt:placeholder="Name"/>
<p:commandButton value="#{guestList.selectedGuest == null ? 'Create Guest' : 'Update Guest'}"/>
</p:outputPanel>
</p:dialog>
</h:form>
The hasSelected() method evaluates whether the selected guest is null or not, returning true if not null. The selectedGuest should be set when the commandButton is clicked so that an object is available for retrieval by the dialog, however, with tracers in the get/set for selectedGuest, I am not seeing the setter called with the above snippet. If I remove the inputText, then even though the hasSelected is still returning false, and thus the 'New Guest' is heading the dialog, the outputText is filled with a value.
I found this great post talking about the order of execution with respect to the action, action listener, etc., but don't think this quite my issue: Differences between action and actionListener.
So the ultimate question is why will my setter get called with the command button when I only have an outputText, but with an inputText, I never see it called in the log?
I appreciate the time and help anyone can provide.
Even if we fix your problem, this construct
<p:inputText value="#{guestList.hasSelected() ? '' : guestList.selectedGuest.name}">
is not ever going to work. It needs to reference a model property, not an empty string.
You'd best just reuse the edit form and let the create button precreate an empty entity. This would simplify a lot in the view side. It'd be more easy if the entity has an #Id property which is only present when it's persisted in the database.
Here's a kickoff example:
<h:form id="entitiesForm">
<p:dataTable id="entitiesTable" value="#{bean.entities}" var="entity">
<p:column>#{entity.foo}</p:column>
<p:column>#{entity.bar}</p:column>
<p:column>
<p:commandButton id="edit" value="Edit"
process="#this" action="#{bean.edit(entity)}"
update=":entityDialog" oncomplete="PF('entityDialog').show()" />
<p:commandButton id="delete" value="Delete"
process="#this" action="#{bean.delete(entity)}"
update=":entitiesForm:entitiesTable" />
</p:column>
</p:dataTable>
<p:commandButton id="add" value="Add"
process="#this" action="#{bean.add}"
update=":entityDialog" oncomplete="PF('entityDialog').show()" />
</h:form>
<p:dialog id="entityDialog" widgetVar="entityDialog"
header="#{empty bean.entity.id ? 'New' : 'Edit'} entity">
<h:form id="entityForm">
<p:inputText id="foo" value="#{bean.entity.foo}" />
<p:inputText id="bar" value="#{bean.entity.bar}" />
<p:commandButton id="save" value="#{empty bean.entity.id ? 'Create' : 'Update'} entity"
process="#form" action="#{bean.save}"
update=":entitiesForm:entitiesTable" oncomplete="PF('entityDialog').hide()" />
</h:form>
</p:dialog>
With this #ViewScoped bean:
private List<Entity> entities; // +getter
private Entity entity; // +getter
#EJB
private EntityService entityService;
#PostConstruct
public void load() {
entities = entityService.list();
entity = null;
}
public void add() {
entity = new Entity();
}
public void edit(Entity entity) {
this.entity = entity;
}
public void save() {
entityService.save(entity); // if (id==null) em.persist() else em.merge()
load();
}
public void delete(Entity entity) {
entityService.delete(entity); // em.remove(em.find(type, id))
load();
}
See also:
Creating master-detail pages for entities, how to link them and which bean scope to choose
Keep p:dialog open when a validation error occurs after submit

disable a particular button in a datatable, jsf

I have a data table with with two columns- Title and Action
Title is populated from a list in a managed bean and for each title in the list the datatable has a button called Confirm under Action column.
When the user clicks on the Confirm button, a dialog is displayed with additional information and another button called Submit.
If the user hits the Submit button inside that dialog a variable confirmDate is set in the backing bean, of the confirmDate is not null, I need to disable the particular Confirm button under the Action column in the main data table. Right now if I disable it, all the Confirm button is getting disabled. How do I disable only the selected confirm button. Really appreciate your help on this.
main data table
<h:panelGrid id="notificationList" width="100%">
<h:panelGroup >
<p:dataTable var="dt" value="#
{myBean.listAll}" id="titles" rowKey="#{dt.id}">
<f:facet name="header">
<h:outputText value = "Title List"/>
</f:facet>
<p:column headerText ="Title">
<h:outputText value="#{dt.title}"/>
</p:column>
<p:column headerText="Action">
<p:commandButton id="nID"
value="Confirm"
oncomplete="myDialog.show();"
process="#this"
disabled= "#{not empty dt.confirmDate}
update="#form">
<f:setPropertyActionListener value="#{dt}" target="#
{myBean.selectedTitle}"/>
</p:commandButton>
</p:column>
</p:dataTable>
</h:panelGroup>
</h:panelGrid>
Hard to say with your code, maybe all your dt objects which you retrieve via listAll are identical objects. How do you set up the list?
Anyhow this should work (simplified):
<p:dialog widgetVar="dlg">
<p:commandButton value="Submit" action="#{myBean.updateNotificationConfirmDate}" oncomplete="dlg.hide()"
update="notificationList" />
</p:dialog>
<p:dataTable id="notificationList" var="dt" value="#{myBean.tableData}">
<p:column>
<p:commandButton value="Confirm" process="#this" disabled="#{!empty dt.confirmDate}" update="#form"
oncomplete="dlg.show();">
<f:setPropertyActionListener value="#{dt}" target="#{myBean.selectedTitle}" />
</p:commandButton>
</p:column>
</p:dataTable>
And the backing bean (whatever your DT is :)):
#ManagedBean
#ViewScoped
public class MyBean {
private List<DT> tableData = new ArrayList<DT>();
private DT selectedTitle;
public MyBean() {
tableData.add(new DT(1L, "title1", null));
tableData.add(new DT(2L, "title2", null));
tableData.add(new DT(3L, "title3", null));
tableData.add(new DT(4L, "title4", null));
}
public DT getSelectedTitle() {
return selectedTitle;
}
public void setSelectedTitle(DT selectedTitle) {
this.selectedTitle = selectedTitle;
}
public List<DT> getTableData() {
return tableData;
}
public void updateNotificationConfirmDate() {
selectedTitle.setConfirmDate(Calendar.getInstance());
}
}

Resources