Primefaces p:commandlink in p:datatable giving wrong value - jsf-2

I have a datatable which consists of a list of names taken from database. These names are displayed using the commandlink. The code is shown below:
<h:form id="formp">
<p:dataTable id="listpat" var="p" value="#{loginBean.patient}">
<p:column>
<p:commandLink value="#{p.firstname} #{p.lastname}" action="# {loginBean.getPatientID(p.firstname)}" onclick="tabview.select(1);">
</p:commandLink>
</p:column>
</p:dataTable>
</h:form>
clicking the commandlink calls a method getPatientID(p.firstname) in the backing bean. I realised the name on the link i click on does not correspond to what is in the backing bean. (e.g. the name clicked on in the commandlink is not the same as the name gotten by passing into the backing bean). What could be the reason? How can i solve it?
public void getPatientID(String fname) {
System.out.println(fname);
}

<p:commandLink value="#{p.firstname} #{p.lastname}" action="#{loginBean.getPatientID(p.firstname)}" onclick="tabview.select(1);">
<f:setPropertyActionListener target="#{loginBean.patient.firstname}" value="#{p.firstname}"
</p:commandLink>
maybe this will work

Related

How to dynamically get value of component p:inputText inside a datatable?

I have a primefaces Datatable:
<p:dataTable id="tabela" var="item"
value="#{myBean.lista}"
rowIndexVar="rowindex">
<p:column>
<p:inputText
required="true" id="inputAliquota" value="#{item.taxa}"
>
</p:inputText>
</p:column>
</p:dataTable>
In my backing bean I have a lista:
private List<Aliquota> lista;
And a Button to remove columns from my datatable:
<p:commandLink
immediate="true" id="botaoExcluir"
action="#{myBean.excluirAliquota}"
>
<f:setPropertyActionListener value="#{item}"
target="#{myBean.aliquota}" />
</p:commandLink>
When I start the bean I populate "lista" with 5 empty Aliquota objects.
In excluirAliquota method I get the object that has to be removed, compare with the values of the List and delete it. But I'm having problems. When the user change the value of inputText the change don't reflect the Aliquota object on list.
My question is how to set this value without submit it?
You cannot reflect the value on the backing bean without submitting it. However, you can submit it using Ajax by adding a listener to the input text. The listener method doesn't have to do anything, it can be empty, but it needs to be there for an Ajax submit. It can be something like that:
<p:dataTable id="tabela" var="item"
value="#{myBean.lista}"
rowIndexVar="rowindex">
<p:column>
<p:inputText
required="true" id="inputAliquota" value="#{item.taxa}"
>
<p:ajax listener="#{myBean.dummyListener()}"/>
</p:inputText>
</p:column>
</p:dataTable>
This will instantly reflect all changes in the inputText to the taxa field of the corresponding item. If that's what you want, you can use this method.

Primefaces commandButton inside dialog not firing backing bean's method

I've just started learning JSF and PrimeFaces, and as soon as I solve a problem (with your help), another one arises. I have a datatable showing some data about my application's users; in the last column, a commandButton invokes a dialog allowing the corresponding data to be edited. The dialog actually interacts with the backing bean, since the fields are correctly precompiled with the existing data, but the "Submit changes" commandButton doesn't fire the proper editUser() method!
I've searched everywhere for a solution to my problem, but none of the threads on the PrimeFaces forums nor any question here on Stack Overflow helped me: I tried all combinations of action, actionListener, inner <h:form>, outer <h:form>, even the dreaded nested <h:form>, but the underlying method is still not called.
Thank you all, people!
EDIT: I included some more xhtml. Just to be clear: in the datatable I'm implementing both single and multiple selection mechanisms. The single selection is performed by the editButton in the last column and triggers the editDialog that's giving me pain, while multiple selection is enabled by the checkboxes in the first column and is targeted by a commandButton at the bottom of the table that deletes all selected users; of course they store the selections in different fields in the backing bean (selectedUser and selectedUsers[], respectively).
xhtml file
<h:form id="tableForm">
<p:dataTable id="userList" var="user" value="#{userListBean.userList}"
selection="#{userListBean.selectedUsers}" rowKey="#{user.username}">
<!-- this is a checkbox column I use for multiple selection -->
<p:column selectionMode="multiple" style="width:2%"/>
<!-- other datatable columns -->
<!-- this is the button column that triggers the dialog -->
<p:column style="width:4%">
<p:commandButton id="editButton" update=":tableForm:editUserData"
oncomplete="PF('editDialog').show()" title="Edit" icon="ui-icon-pencil">
<f:setPropertyActionListener target="#{userListBean.selectedUser}"
value="#{user}" />
</p:commandButton>
</p:column>
</p:datatable>
<p:dialog id="editDlg" widgetVar="editDialog" header="Edit User"
showEffect="fade" hideEffect="fade" modal="true" dynamic="true">
<h:panelGrid columns="6" id="editUserData">
<p:outputLabel for="editUsername">Username:</p:outputLabel>
<p:inputText disabled="true" id="editUsername" value="#{userListBean.selectedUser.username}" />
<p:message for="editUsername" />
<!-- and other fields like that -->
</h:panelGrid>
<p:commandButton id="submitChanges" action="#{userListBean.editUser()}"
value="Submit changes" oncomplete="PF('editDialog').hide();" />
</p:dialog>
</h:form>
Backing bean
#ManagedBean(name="userListBean")
#ViewScoped
public class UserListBean {
private UserDTO selectedUser;
public UserListBean() {
}
//some methods...
public String editUser() {
System.out.println("------------------ EDIT TRIGGERED! -------------------");
System.out.println(selectedUser.getUsername());
//this stuff never gets printed, so the method is never called!
}
//getters and setters
}
Actually, the only thing didn't come to my mind turned out to be the one that worked.
I sorted out my issue by using THREE forms (as I mentioned in my question, I had already tried out all possible combinations of one and two forms, even nested ones), like this:
<h:form id="tableForm">
<!-- here lies the p:dataTable -->
</h:form>
<p:dialog>
<h:form id="dialogForm">
<!-- here lies the h:panelGrid with the editable fields -->
</h:form>
<h:form id="buttonForm">
<!-- and HERE goes the commandButton, alone -->
</h:form>
</p:dialog>
It looks like everyone solves this problem in ways that don't work for others :) .

ignoreValidationFailed doesn´t work inside p:dataTable

I am using actionListener ajax call inside datatable and trying to do the following :
skip validation
update the model with the inserted values
I knew that omnifaces utility liberary by BalusC can do this using o:ignoreValidationFailed
But it failed with me to work inside primefaces datatable.
Also I found that it failed to work inside ui:repeat in another post here
I dont know if its a bug or not.
here is my code example
<o:form id ="trans_desc_form">
<p:outputPanel id="stkdetailsid">
<p:dataTable id="transactiondetailsid" value="#{stockTransactionsBean.stkTransHeader.stkTransDetailsList}"
var="stkTransDet" rowIndexVar="rowIndex">
<p:column>
<f:facet name="header">
<h:outputText value="Item Code" />
</f:facet>
<p:autoComplete id="dd" required="true"
value="#{stkTransDet.item}" var="i" itemLabel="#{i.itemno} #{i.itemnamee}"
itemValue="#{i}" converter="itemsConverter"
completeMethod="#{stockTransactionsBean.completeItems}"/>
</p:column>
<p:column>
<p:commandButton value="-" update="#form" process="#form"
actionListener="#{stockTransactionsBean.removeRow(rowIndex)}">
<o:ignoreValidationFailed />
</p:commandButton>
</p:column>
</p:dataTable>
</p:outputPanel>
</o:form>
As a workaround, I added
1- add a condition to the required field to know if the ajax come from submit button or not
to the autoComplete component where the trans_desc_form is thte entire form id and savetransid is the submit button save id
required="#{!empty param['trans_desc_form:savetransid']}"/>
2- I removed #NotNull from my JPA entity which force the validation
#JoinColumn(name = "ITEMNO", referencedColumnName = "ITEMNO")
#ManyToOne(optional = false, fetch = FetchType.LAZY)
//#NotNull
private Item item;
To skip validation you can use the immediate="true" attribute on your p:commandButton

primefaces command button action invoked after datatable load

I am facing a problem with primefaces command button and datatable. I have two buttons inside the datatable. when I click on the button everytime datatable loaded first and then button action invoked. I just want to avoid the datatable loading when button is clicked.
<p:dataTable id="alphaTable" var="cs" binding="#{challengeSetBean.alphaChallengeSetTable}"
value="#{challengeSetBean.challengeSet}" styleClass="myTable"
style="list-style-type:none;width:600px;border:1px;" >
<p:column id="col" style="width:20px;font-size:12px;padding-left:7px;padding-bottom:7px;padding-top:7px;">
..................
................
</p:column>
<p:column style="width:28px;font-size:9px;padding-left:7px;padding-bottom:7px;padding-top:7px;">
<p:commandButton value="#{msg.updateAccount_reset}" action="#{challengeSetBean.editAnswer()}" immediate="true" rendered="#{!cs.editMode}" process="#this" update="col" >
</p:commandButton>
<p:commandButton value="#{msg.common_save}" action="#{challengeSetBean.saveAnswers()}" rendered="#{cs.editMode}" ajax="true" immediate="true" update="#form"/>
<p:commandButton value="#{msg.cancel}" action="#{challengeSetBean.cancelAnswer()}" rendered="#{cs.editMode}" ajax="true" immediate="true" update="#form"/>
<p:commandButton value="#{msg.common_delete}" action="#{challengeSetBean.deleteAnswer()}" rendered="#{!cs.editMode}" immediate="true" update="#form"/>
</p:column>
</p:dataTable>
Put the bean in the view scope so that it would be instantiated only once on initial GET request and be reused on subsequent postbacks. Remove the binding attribute from the <p:dataTable> so that the view scoped bean won't be recreated due to chicken-egg JSF issue 1492. Now you can just load the challengeSet in the (post)constructor of the bean. It won't be invoked during subsequent postbacks.
See also:
Binding kills backing beans...what am I doing wrong?
How can I pass selected row to commandLink inside dataTable?
Recommended JSF 2.0 CRUD frameworks

p:selectOneMenu first ajax request issue

I have a problem with PrimeFaces p:selectOneMenu component when I try to update a p:dataGrid by changing the SelectOneMenu's value.
Xhtml:
<p:selectOneMenu value="#{bussinessOwnersViewerMB.selectedCity}" effect="explode">
<f:selectItems value="#{bussinessOwnersViewerMB.cities}" var="city" itemLabel="#{city.cityName}" itemValue="#{city.cityId}"/>
<p:ajax listener="#{bussinessOwnersViewerMB.handleCityChange}" update="mainform:bolist"/>
</p:selectOneMenu>
<p:dataGrid id="bolist" var="bo" value="#{bussinessOwnersViewerMB.bOwners}" columns="3" rows="#{bussinessOwnersViewerMB.os}">
<p:column>
<p:panel header="#{bo.bOName}">
<h:panelGrid columns="1">
<p:graphicImage value="/resources/images/#{bo.boType}/#{bo.bOId}/mainProfile.jpg"/>
</h:panelGrid>
</p:panel>
</p:column>
</p:dataGrid>
The problem is, when I change the selectOneMenu's value at the first time the datagrid doesn't get updated. What happen is only the postconstructor method is called, after the first change it works fine.
My managed bean is a viewscoped managed bean.
The listener method "bussinessOwnersViewerMB.handleCityChange" is :
public void handleCityChange(ValueChangeEvent event) {
bOwners = bovb.loadAllDistributerByType(new Integer(selectedCity)); // selectedcity is the selected item id
os = Integer.toString(bOwners.size());
}
In the past you couldn't update a dataGrid like that; you had to wrap it in a panelGroup. I don't know wether or not that has changed, but I still do it like that and it still works. So just put your dataGrid inside a panelGroup and update the panelGroup (instead of the dataGrid) in your ajax tag.
In my case the problem was generated by a <p:panel> that contains a <h:panelGroup>, so the partial submit using <p:ajax> did not work. This problem happen when in the form there are empty fields which has required=true.
I updated the <p:panel> in <h:panelGroup>.
From:
<p:panel ... >
...
<h:panelGroup ...>
<!-- Form inside -->
</h:panelGroup>
...
</p:panel>
to
<h:panelGroup ... >
...
<h:panelGroup ...>
<!-- Form inside -->
</h:panelGroup>
...
</h:panelGroup>

Resources