A p:commandLink inside a p:dataTable does not work [duplicate] - jsf

This question already has answers here:
commandButton/commandLink/ajax action/listener method not invoked or input value not set/updated
(12 answers)
Closed 7 years ago.
I am using PrimeFaces 5.2 and at a place in my web app. I am displaying a data table is which corresponding to each row. I am giving an edit link (<p:commandLink>) to edit the the fields of corresponding entity on next page but the link is not working at all. Here is the XHTML content.
<p:dataTable id="tickets" var="ticket"
value="#{ticketController.ticketModels}" paginator="true" rows="10"
filteredValue="#{ticketController.filteredTickets}">
<p:column headerText="Ticket Id" sortBy="#{ticket.ticketId}">
<p:commandLink action="viewDetailedTicket">
<h:outputText value=" #{ticket.ticketId}"></h:outputText>
</p:commandLink>
</p:column>
<p:column headerText="Summary" filterBy="#{ticket.summary}"
filterMatchMode="contains" sortBy="#{ticket.summary}">
<h:outputText value="#{ticket.summary}" />
</p:column>
<p:column headerText="Priority">
<h:outputText value="#{ticket.priority}" />
</p:column>
.
...............................
</p:dataTable>
The following is my backing bean:
#ManagedBean
public class TicketController {
#ManagedProperty(value = "#{ticketpojo}")
private Ticket ticket;
private TicketDao tDao;
private TicketModel ticketModel;
public TicketModel getTicketModel() {
return ticketModel;
}
public void setTicketModel(TicketModel ticketModel) {
this.ticketModel = ticketModel;
}
public TicketController() {
tDao = new TicketDao();
}
public String viewDetailedTicket() {
ticketModel = tDao.getTicket(ticketId);
return "viewDetailedTicket";
}
}
When I hover, over the link , the tooltip at the bottom of the browser shows http://localhost:8080/JSF_1/view/viewTicket.xhtml# , a '#' is appended to the end of the current page URL. When clicked it remains on the same page.
I have tried putting the link outside the data-table that also didn't work .

A commandLink or any action that you'd like to do with JSF/primefaces must be inside a form. Otherwise no HTTP Post can be performed. I suggest to use one form for the whole datatable. Otherwise there will be a lot of forms for the multiple rows.

Related

When nesting another datatable in rowexpansion, splitbutton stops working when 2 or more main rows are loaded

So I'm trying to nest a datatable within another datatable in the rowexpansion tag as follows:
<h:form>
<p:dataTable var="item"
value="#{bean.items}">
<p:column>
<p:rowToggler/>
</p:column>
<p:column headerText="Item Name">
<h:outputText value="#{item.name}"/>
</p:column>
<p:rowExpansion>
<p:dataTable var="subitem"
value="#{item.subitems}">
<p:column headerText="Subitem Name">
<h:outputText value="#{subitem.name}" />
</p:column>
<p:column>
<p:splitButton value="Save" action="#{bean.save}">
<p:menuitem value="Update" action="#{bean.update}"/>
<p:menuitem value="Delete" action="#{bean.delete}"/>
</p:splitButton>
</p:column>
</p:dataTable>
</p:rowExpansion>
</p:dataTable>
</h:form>
the testing methods in the bean are just
public void save() {
addMessage(FacesMessage.SEVERITY_INFO, "Success!", "Saved subitem");
PrimeFaces.current().ajax().update(":frmTopbar");
}
public void update() {
addMessage(FacesMessage.SEVERITY_INFO, "Success!", "Updated subitem");
PrimeFaces.current().ajax().update(":frmTopbar");
}
public void delete() {
addMessage(FacesMessage.SEVERITY_INFO, "Success!", "Deleted subitem");
PrimeFaces.current().ajax().update(":frmTopbar");
}
public void addMessage(FacesMessage.Severity severity, String summary, String detail) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(severity, summary, detail));
}
If only a single item and its subitems is loaded, everything displays and splitbutton buttons work fine.
The bean just sends a FacesMessage to test and like I said, the message is properly shown for each of the 3 buttons.
But as soon as I load 2 or more items and their subitems, everything looks visually correct, but the commands in splitbutton no longer reach bean, so no FacesMessage is sent.
Does anyone have a clue about what is going on or a suggestion as to what can be done to fix it?
I'm using primefaces v11.0
Thanks a lot!
I seem to have found a workaround with p:remoteCommand using BalusC's tips.
So what I've done, is place this somewhere in my page that will map a javascript function to a bean method.
<p:remoteCommand name="splitButtonMenuitemClicked" actionListener="#{bean.save}" style="display: none;" />
I then place this jquery code in my page to catch the click event from any split button:
jQuery( document).delegate( ".ui-splitbuttonmenu .ui-menuitem-link", "click",
function(e){
var menuitemText = $(this).find("span.ui-menuitem-text");
var itemText = $(menuitemText).text();
splitButtonMenuitemClicked([{ name: "fooName", value: itemText }])
}
);
Now in my bean function, I just retrieve my parameter as follows:
public void save() {
String fooName= FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("fooName");
//fooName is unique key in may table, so it works well to work on the correct entity
...
}
It'll do for now, although it would be nice if the components worked as one hopes.

How can set value with selectBooleanCheckbox and Delete? [duplicate]

This question already has answers here:
commandButton/commandLink/ajax action/listener method not invoked or input value not set/updated
(12 answers)
How to use <h:form> in JSF page? Single form? Multiple forms? Nested forms?
(2 answers)
Closed 3 years ago.
I am doing a mini jsf project that is created by using jpa. I have listed costumers and I can remove them one by one, but if I want to remove selected costumers I cannot do it.
This part is from Costumer class
#Transient
private Boolean selection = false;
And this part is from CostumerBean
Costumer costumer = new Costumer();
private List<Costumer> costumerList = new ArrayList<>();
//(getters and setters)
public void removeSelected() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
for (Costumer cos : costumerList) {
if (cos.getSelection()) {
em.remove(em.contains(costumer) ? customer : em.merge(costumer));
}
}
em.getTransaction().commit();
musteri = new Musteri();
}
And finally here is the xhtml page :
<h:form id="firstForm">
<p:commandButton action="#{customerBean.removeSelection}" value="Remove"
update="customerForm">
</p:commandButton>
</h:form id="firstForm">
<h:form id="customerForm">
<p:dataTable value="#{customerBean.customerList}" var="cst"
id="cstTable">
<p:column>
<f:facet name="header">Select</f:facet>
<p:selectBooleanCheckbox value="#{cst.selection}" />
</p:column>
<p:column>
<f:facet name="header">Name</f:facet>
#{cst.name}
</p:column>
</h:form id="customerForm">
I reckon actual problem is I cannot make selection field in Costumer.java true. No action I see.?

commandLink in primefaces datatable doesn't work if I add the filteredValue attribute

I have a primefaces datatable with a <p:commandLink> in each row. The user clicks it to see a different page with details about the record he selected. It was working fine until I add a filteredValue in my datatable. I need this attribute (filteredValue) in order to correctly filter and sort my datatable, as shown in this question.
But after adding this attribute, my commandLink stops working. How can I make it work with the attribute?
Here's my datatable:
<p:dataTable var="prot" value="#{myBean.listaProtocolos}" rows="15" filteredValue="#{myBean.listaProtocolosFiltrados}" sortBy="#{prot.dataEntradaArea}" sortFunction="#{myBean.sortXMLDatas}" sortOrder="descending" paginator="true" style="font-size: 0.9em;" paginatorPosition="bottom">
<p:column filterBy="${prot.nrProtocolo}" filterMatchMode="contains" width="8%" style="text-align:center">
<f:facet name="header">ID</f:facet>
<p:commandLink action="#{myBean.verDetalhesProtocolo}" process="#this messages" update="#this messages">
<h:outputText value="#{prot.nrProtocolo}" style="text-decoration: underline;"/>
<f:setPropertyActionListener target="#{myBean.nrProtocolo}" value="#{prot.nrProtocolo}" />
</p:commandLink>
</p:column>
(etc)
and the relevant pieces of myBean:
public void verDetalhesProtocolo() {
for(ProtocoloMY pro : this.listaProtocolos){
if(pro.getNrProtocolo().trim().equalsIgnoreCase(this.nrProtocolo.trim())) {
this.protocolo = new ProtocoloMY(pro);
break;
}
}
FacesContext facesContext = FacesContext.getCurrentInstance();
facesContext.getExternalContext().redirect("detalhes_protocolo_processo.xhtml");
//(This method isn't even called when I add the attribute filteredValue to my datatable)
public String getNrProtocolo() {
return nrProtocolo;
}
public void setNrProtocolo(String nrProtocolo) {
this.nrProtocolo = nrProtocolo;
}
public List<ProtocoloMY> getListaProtocolos() {
return listaProtocolos;
}
public List<ProtocoloMY> getListaProtocolosFiltrados() {
return listaProtocolosFiltrados;
}
public void setListaProtocolosFiltrados(List<ProtocoloMY> listaProtocolosFiltrados) {
this.listaProtocolosFiltrados = listaProtocolosFiltrados;
}
public void setListaProtocolos(List<ProtocoloMY> listaProtocolos) {
this.listaProtocolos = listaProtocolos;
}
And I almost forgot to say: There's some network traffic happening when I click the link, but nothing is shown in my backend console and the method in my bean isn't called.
I'm running primefaces v6.0.
For PrimeFaces to be able to track which row by its unique id you need to add the attribute rowKey="#{row.id}" to your p:datatable using whatever value in your row POJO that makes it unique.

Primefaces' commandLink works only on the first page of a dataTable

I have a column with p:commandLink inside p:dataTable, which has a paginator. When user clicks on a commandLink, a dialog opens, displaying data of that row.
datatable html code:
<p:dataTable id="dtSample" value="#{sessionBean.sampleList}"
binding="#{requestBean.dtSampleList}"
paginator="true" paginatorPosition="bottom"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="#{10,25,50}"
currentPageReportTemplate="({startRecord} of {totalRecords})"
var="item" emptyMessage="No entries." rows="10" rowKey="#{item.id}">
<p:column headerText="Id">
<p:commandLink id="lnkSample"
action="#{requestBean.onLinkClick(item)}"
oncomplete="PF('dlgSample').show();"
update="#(.dialogClass)">
<h:outputText value="#{item.id}" />
</p:commandLink>
</p:column>
<p:column headerText="Code">
<h:outputText value="#{item.code}" />
</p:column>
<p:column headerText="Description">
<h:outputText value="#{item.descr}" />
</p:column>
</p:dataTable>
Request bean:
public class RequestBean {
private SessionBean sessionBean;
private DataTable dtSampleList;
public void init() {
// load samle list
loadSampleList();
}
public String onLinkClick(Sample sample) {
getSessionBean().setSelectedSample(sample);
return "success";
}
private void loadSampleList() {
List<Sample> list = new ArrayList<Sample>();
for (int i = 0; i < 100; i++) {
Sample tmp = new Sample();
tmp.setId(new BigDecimal(i + 1));
tmp.setCode("code" + (i + 1));
tmp.setDescr("desc" + (i + 1));
list.add(tmp);
}
getSessionBean().setSampleList(list);
}
// getters and setters
}
Session bean:
public class SessionBean implements Serializable {
private static final long serialVersionUID = 1L;
private List<Sample> sampleList;
private Sample selectedSample;
// getters and setters
}
dialog html code:
<p:dialog id="dlgSample" closeOnEscape="true" widgetVar="dlgSample"
styleClass="dialogClass" modal="true">
<p:panelGrid columns="1">
<h:outputText value="Id: #{sessionBean.selectedSample.id}" />
<h:outputText value="Code: #{sessionBean.selectedSample.code}" />
<h:outputText value="Description: #{sessionBean.selectedSample.descr}" />
</p:panelGrid>
</p:dialog>
When I click on a link on the first page of a datatable, link action is executed and a dialog, displaying row data, is properly refreshed. But when I move to any of the following pages of a datatable, clicking a link doesn't refresh the data in a dialog (the link action is not called, so the data in a dialog is wrong - selectedSample variable has old value). Of course when I go back to the first page of the datatable, command link works again (action method is called and data is refreshed).
What am I doing wrong? Why is action method not called on any datatable page?
I'm using Primefaces 5.2.
Looks like the problem was in a PF dataTable component. There were first and rows attributes missing and after adding them, commandLinks on all pages work as expected.
What am I doing wrong? Why is action method not called on any datatable page?
A common misstake leading to that behaviour is that your state is not consistent: To process the form submit, JSF will recreate the exact same view as in the prior request, and then apply the changes (execute the action)
If this new view is now different than the view before the submit was, every action is aborted and not invoked. (Different in terms of involved elements. I.e. if your commandLink was rendered="true" before submitting, it needs to be rendered="true" during the APPLY_REQUEST_VALUES-Phase).
So, from your description I would assume, that your table is falling back to page 1, which will remove any link on page 2 from the view and abort it's view action, because the element is no longer rendered.
For the same reason, links on page 1 are working, because even if your table looses track of the current page - it will render page 1, so you have the same view as before, so the submission works.
You could easily verify this, by increasing the number of elements per page and see that every link moved from page 2 to page 1 is now working.
But without seeing the whole bean I can only assume this. For easy testing, set your bean to #SessionScoped and see if this resolves it.
For more ideas, see this post: commandButton/commandLink/ajax action/listener method not invoked or input value not updated
When putting components such as p:commandLink in a p:dataTable row, you should always specify
process="#this"
So, in your case, I would try :
<p:commandLink id="lnkSample"
action="#{bean.onLinkClick(item)}"
oncomplete="PF('dlgSample').show();"
update="#(.dialogClass)">
<h:outputText value="#{item.id}" />
</p:commandLink>
Doing so, you are sure that only the click on the link will be processed, and no other submission will be performed.

Primefaces datatable onEdit() edits the wrong entry if an entry has been added before refreshing the view

i've got a question concerning Primefaces (version 5.0) and their datatable.
If I have a p:datatable and I want to edit a cell or row (doesn't matter - behaviour is the same in that case) AND someone added a new entry to that database, I edit the new entry instead of the old.
Well. Here are some code-snippets:
my index.xhtml:
<h:form id="viewChanges">
<p:dataTable id="changeTable"
widgetVar="changeTable"
value="#{changeController.list}" var="item"
selection="#{changeController.selectedChangeEntry}"
selectionMode="single" rowKey="#{item.id}"
sortBy="#{item.id}" sortOrder="descending"
editable="#{lDAPUserController.loggedIn}"
style="width: auto">
<p:ajax event="rowEdit"
listener="#{changeController.onRowEdit}"
update=":growlInfo, :growlError, :viewChanges:changeTable" />
..output of columns..
<p:column style="width:32px">
<p:rowEditor />
</p:column>
</p:dataTable>
</h:form>
my changeController.java
#ManagedBean(name = "changeController")
#ViewScoped
public class ChangeController implements java.io.Serializable {
attributes, getter, setter, other methods etc..
public void onRowEdit(RowEditEvent event) {
FacesMessage msg = new FacesMessage("Change Edited", ((Change) event.getObject()).getId());
FacesContext.getCurrentInstance().addMessage(null, msg);
}
}
Well with this it's already possible to replicate the error.
Little Example: We have a dataset with 3 entries. - id=1,2,3
We open a browser[1] and see the 3 datasets. We now open a private tab[2] and go to the same site and add a new entry. Without refreshing [1] we edit the entry with id=3. All of the sudden we edited entry with id=4.
Could someone explain me why this is happening? Is it me or is it bug in primefaces? Wrong Scope?

Resources