I have a selectonemenu within a datatable column. The selected options are messed up when I delete a row and it doesn't seems to reflect the value in the backend bean. For example, I selected Item A in the first row, then add another row and select Item B in the second row, then when I delete the first row, the second row is move up with Item A selected, but the backend value of second row is still Item B and Item A is removed from the collection.
<p:dataTable id="insertDetailTable" styleClass="data-table"
rowIndexVar="rowIndex" var="receivingDetail"
value="#{receivingController.receiving.receivingDetails}">
<p:column headerText="Item">
<p:selectOneMenu styleClass="input" id="item"
value="#{receivingDetail.item}" required="true"
requiredMessage="Item is required" converter="itemConverter">
<f:selectItem itemLabel="Select an item" itemValue="#{null}"
noSelectionOption="true" />
<f:selectItems value="#{receivingController.items}" var="item"
itemLabel="#{item.code} - #{item.name}" itemValue="#{item}" />
<p:ajax update="insertDetailTable" />
</p:selectOneMenu>
</p:column>
<p:column styleClass="action-cell">
<f:facet name="header">
<p:commandButton icon="ui-icon-plus" value="Add"
action="#{receivingController.insertDetail('insert')}"
immediate="true" />
</f:facet>
<p:commandButton icon="ui-icon-trash"
action="#{receivingController.deleteDetail('insert', receivingDetail)}"
immediate="true">
<p:confirm header="Confirmation"
message="Do you wish to remove the selected detail?"
icon="ui-icon-alert" />
</p:commandButton>
</p:column>
</p:dataTable>
The backend code of adding a new row and deleting a row:
public void insertDetail(String owner) {
ReceivingDetail receivingDetail = new ReceivingDetail();
receivingDetail.setReceiving(receiving);
receivingDetail.setQtyStored(new BigDecimal("0.00"));
receiving.getReceivingDetails().add(receivingDetail);
RequestContext context = RequestContext.getCurrentInstance();
if (owner.equals(OWNER_INSERT)) {
context.update("insertForm");
context.execute("PF('insertDialogWV').show();");
} else if (owner.equals(OWNER_UPDATE)) {
context.update("updateForm");
context.execute("PF('updateDialogWV').show();");
}
}
public void deleteDetail(String owner, ReceivingDetail receivingDetail) {
receiving.getReceivingDetails().remove(receivingDetail);
ItemService itemSvc = (ItemService) getService(ItemService.class);
setItems(itemSvc.find());
RequestContext context = RequestContext.getCurrentInstance();
if (owner.equals(OWNER_INSERT)) {
context.update("insertForm");
context.execute("PF('insertDialogWV').show();");
} else if (owner.equals(OWNER_UPDATE)) {
context.update("updateForm");
context.execute("PF('updateDialogWV').show();");
}
}
Any idea what went wrong with my code?
I am using Primefaces 5 and JSF 2.2.
This is the first time I posting a question, not sure did I do it right, let me know if I need to correct anything, thanks in advance.
Edited:
Just in case this information is required, the datatable resides within a dialog as such.
<h:form id="insertForm">
<p:dialog id="insertDialog" widgetVar="insertDialogWV" modal="true"
draggable="false" resizable="false" header="Add Record"
closable="false">
</p:dialog>
</h:form>
Removed immediate="true" in the command button and it works, the table select and show the value according to the backend bean properly.
Related
I have a big problem with Primefaces accordion.
I have an outputPanel with an header and an accordion with 2 tabs.
If I close the first tab and change a field in the second tab, it open the first tab and close the second. How can I keep the status of the tabs?
This is a simple example:
<p:outputPanel id="content">
<p:outputPanel id="header" />
<p:accordionPanel multiple="true">
<p:tab title="firstTab">
<p:panel>
<p:inputText id="firstInput" value="firstInput">
<p:ajax event="change" update="content" />
</p:inputText>
</p:panel>
</p:tab>
<p:tab title="secondTab">
<p:panel>
<p:inputText id="secondInput" value="secondInput">
<p:ajax event="change" update="content" />
</p:inputText>
</p:panel>
</p:tab>
</p:accordionPanel>
</p:outputPanel>
How can i resolve it? Any suggestion?
AccordionPanel has an attribute called activeIndex, you could set this attribute from your MB so it doesn´t change after an update. See for instance https://www.primefaces.org/docs/vdl/6.1/core/primefaces-p/accordionPanel.html
Based on cagatay civici's answer provided in the link by #Christian I created a simple example, because it was not working out of the box for me.
The example.xthml:
<h:form styleClass="accordionForm">
<p:accordionPanel multiple="true"
activeIndex="#{sessionBean.activeTabs}">
<p:ajax event="tabChange" />
<p:ajax event="tabClose" />
<p:tab title="Tab1">
<p:panel>
<p:inputText id="firstInput" value="firstInput">
<p:ajax event="change" update="#(.accordionForm)" />
</p:inputText>
</p:panel>
</p:tab>
<p:tab title="Tab2">
<p:panel>
<p:inputText id="secondInput" value="secondInput">
<p:ajax event="change" update="#(.accordionForm)" />
</p:inputText>
</p:panel>
</p:tab>
</p:accordionPanel>
</h:form>
The sessionBean.java:
#Named("sessionBean")
#SessionScoped
public class SessionBean implements Serializable {
private static final long serialVersionUID = 1L;
private String activeTabs = "";
public String getActiveTabs() {
return activeTabs;
}
public void setActiveTabs(String activeTabs) {
this.activeTabs = activeTabs;
}
}
Explanation:
The two p:ajax tags trigger a POST request if a tab is either opened ("tabChange") or closed ("tabClosed"), since this is the default action for the accordionPanel. Hence, I wrapped the p:accordionPanel with an h:form. If you inspect your network traffic you can see how the list of active tabs is sent to the server.
Bear in mind that I update the surrounding form instead of the accordionPanel itself. Therefore, I use Primefaces Selectors.
After filtering with filterBy selected var instance get lost.
<p:dataTable id="searchResults"
var="searchResult"
value="#{employeeController.searchResults}"
selectionMode="single"
selection="#{employeeController.selectedEmployee}"
rowKey="#{searchResult.id}">
<p:column headerText="Employee Name"
filterBy="#{searchResult.name}"
sortBy="#{searchResult.name}">
<h:outputText value="#{searchResult.name}"/>
</p:column>
</p:dataTable>
<p:commandButton actionListener="#{employeeController.editEmployee(searchResult)}"
icon="ui-icon-pencil"
title="Güncelle" ajax="true" update="#form">
my event does not get the selected searchResult instance but instead a null value
I solved the problem. I was just missing filteredValue.
Currently using primefaces 3.3 and want to refresh the datatable on removing an item from the list.
When I refresh the page, do see updated table, so the list is getting updated in java code.
Thanks for your time and help.
Please let me know where I am misktaken.
Here's the relevant code:
//in xhtml
<p:dataTable id="userConnections" var="connection" value="#{loginBean.userConnectionEmailList}">
<p:column>
<h:outputText value="#{connection.email}" />
</p:column>
<p:column>
<p:commandButton id="deleteButton" icon="ui-icon-close" title="Delete" process="#this" action="#{loginBean.deleteConnectionAction}" update="userConnections">
<f:setPropertyActionListener value="#{connection}" target="#{loginBean.selectedUserConnection}"/>
</p:commandButton>
</p:column>
</p:dataTable>
// java code
public String deleteConnectionAction() {
System.out.println("###deleteConnectionAction ###" + selectedUserConnection.getEmail() );
userConnectionEmailList.remove(selectedUserConnection);
return "";
}
Primefaces 3.5, Mojarra 2.1.14. This is my PF datatable, it contains one non-editable boolean column named 'automatic', and editable 'label' column:
<p:dataTable value="#{bean.contents}" paginator="true" var="row"
editable="true" editMode="cell" rows="25" rowsPerPageTemplate="10,25,50" id="list">
<p:column>
<f:facet name="header"><h:outputText value="header1" /></f:facet>
<p:selectBooleanCheckbox value="#{row.automatic}" disabled="true" id="isAutomatic"></p:selectBooleanCheckbox>
</p:column>
<p:column>
<f:facet name="header"><h:outputText value="header2" /></f:facet>
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{row.label}"></h:outputText>
</f:facet>
<f:facet name="input">
<p:inputText value="#{row.label}"></p:inputText>
</f:facet>
</p:cellEditor>
</p:column>
<p:ajax event="cellEdit" process="#this" listener="#{myBean.onEditLabel}" update="isAutomatic"/>
</p:dataTable>
Cell edit event listener:
public void onEditLabel(CellEditEvent event) {
Object oldValue = event.getOldValue();
Object newValue = event.getNewValue();
if(newValue != null && !newValue.equals(oldValue)) {
DataTable s = (DataTable) event.getSource();
MyEntity d = (MyEntity) s.getRowData();
try {
d.setAutomatic(false);
myDAO.save(d);
addMessage("Change saved!");
} catch (Exception ex) {
addErrorMessage("Label could not be saved!");
getFacesContext().validationFailed();
}
}
}
The cell editor works, sends data to listener, and it is correctly persisted to the database. The 'automatic' flag is also cleared by cell edit event listener, and gets correctly persisted to the database. The problem is that 'automatic' checkbox is not updated on the client.
I also tried
<p:ajax event="cellEdit" process="#this" listener="#{myBean.onEditLabel}" update="list"/>
which correctly updated the checkbox, but also causes focus to be lost, and wastes bandwidth.
How can I update just a specific cell after cellEdit event is fired?
You p:ajax tag is inside p:dataTable no in some specific row or column, so you cent so easy update some relative component id. You can with help of RequestContext update specific component in cell. So, remove update from p:ajax and add this to your onEditLabel method:
RequestContext.getCurrentInstance().update(
s.getClientId(FacesContext.getCurrentInstance()) +
":" + event.getRowIndex() +
":isAutomatic"
);
As you can see, id of component inside cell has row number before id you assigned.
I believe you can solve this without having to know the details of the ID of the component you wish to update. You can pass it as a parameter to the bean.
First, bind the component you wish to update. You don't actual need a bean to which this component is bound to. You just need to define some value which you can use to identify this component later in your JSF. So in your case, you would do something like:
<p:selectBooleanCheckbox binding="#{isAutomaticComponent}" value="#{row.automatic}" disabled="true" id="isAutomatic"></p:selectBooleanCheckbox>
Now access the component when you do your update. ie:
<p:ajax event="cellEdit" process="#this" listener="#{myBean.onEditLabel(isAutomaticComponent.clientId)}" />
Now you can update the component from your cellEdit event method without knowing the contents of the ID. ie:
public void onEditLabel(CellEditEvent event, String idOfComponentToUpdate) {
...
RequestContext.getCurrentInstance().update(idOfComponentToUpdate);
...
Salut :), iam a newbie in primefaces and ajax
Iam using primefaces 3.4, glassfish 3.1, jsf2.0 and ejb 3. I tried to implement primefaces showcase datatable rowediting. But when i validate the updated value into the datatable, i get the old value. This is my code :
<h:form id="form">
<p:growl id="messages" showDetail="true"/>
<p:dataTable var="item" value="#{jSFMBean.allContacts}" id="contactList" editable="true">
<p:ajax event="rowEdit" listener="#{jSFMBean.onEdit}" update="#this :form:messages" />
<p:ajax event="rowEditCancel" listener="#{jSFMBean.onCancel}" update=":form:messages" />
<p:column headerText="EMAIL" style="width:125px">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{item.email}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{item.email}" label="EMAIL"/>
</f:facet>
</p:cellEditor>
</p:column><p:column headerText="Options" style="width:50px">
<p:rowEditor />
</p:column>
</p:dataTable>
<h:outputText value="#{jSFMBean.selectedContact.displayname}" />
the methods are :
public void onEdit(RowEditEvent event) {
this.session.updateContact((Contacts) event.getObject());
FacesMessage msg = new FacesMessage("Edition contact: ", ((Contacts) event.getObject()).getDisplayname());
FacesContext.getCurrentInstance().addMessage(null, msg);
}
(Contacts) event.getObject() always get the old value :(. It's like the getter of the datatable fireup first before ajax update to the database.
what iam i doing wrong ? thank you for your help solving this .
Currently you're editing values within the object. It looks like you still need to make a call back to your database to update the value there.
It seems that whenever you need your dataTable you are getting it from your database and that's why event.getObject() always returns the old value.So in the getter of your datatable you need to add:
if (allContacts== null){
allContacts= (List<Contacts>) yourservice.getAll(); /*this refers to the function that get the list from the database*/
}
return allContacts;
I hope that may help you.
Most probably the problem is with your backing bean. if you have used #Named annotation instead of #ManagedBean (javax.faces.bean.ManagedBean) for your backing bean, you faces this kind of problems. Simply replace
#Named (value="YourBeanName")
with
#ManagedBean (name="YourBeanName")