<h:form ...
<p:dataTable value="#{myBean.list}" var="data" ...
<p:column ...
<h:commandButton action="#{controller.method(data.id)}" />
</p:column>
</p:dataTable>
</h:form>
@ApplicationScoped
public class Controller {
public String method(final Long dataId) {
/* Do business */
return URL_WITH_REDIRECT;
}
}
(using the @ViewScoped
CDI annotation as described here)
@ApplicationScoped
public class Producer {
@Named @ViewScoped @Producer
public MyBean getMyBean() {
final MyBean bean = new MyBean();
bean.list = new ArrayList<Data>(); // where Data has a Long id field
/* Do business and populate list */
return bean;
}
}
GET
the page
POST
ed to server@ViewScoped
beans as expectedcontroller.method
is called with data.id
and accesses beans generated at 1.1
String
GET
next page ...In short: on click, copy the id outside the datatable, and trigger a click on a submit button.
On the h:commandButton
inside the table column added :
onclick="$('input[id*=selectedDataId]').val('#{data.id}'); $('button[id*=callMethod]').trigger('click');"
Outside the table:
<h:inputHidden id="{selectedDataId}"binding="#{selectedDataId}"/>
<p:commandButton type="submit"
id="callMethod"
label="Hidden button"
action="#{controller.method(selectedDataId.value)}"/>
At the end it works, but I was not able to figure out what causes the first & base approach to reinitialize the view scoped bean. Looking at the stack trace (see below) it seems like it is rebuilding the rows.
Does anyone have an explanation, and maybe caveats to look out for regarding this issue?
Where: getPipelinecheckSearchResults
is the call for retrieving the list that backs the table, that causes the producer to be called
I've read following articles / SO questions without gaining any better understanding on why the above (1st) solution works as it does.
ViewScoped bean is recreated everytime I click on commandButton in my dataTable
Why does @PostConstruct callback fire every time even though bean is @ViewScoped? JSF
How can I pass selected row to commandLink inside dataTable?
http://balusc.blogspot.de/2010/06/benefits-and-pitfalls-of-viewscoped.html
https://java.net/jira/browse/JAVASERVERFACES-1492
I've found some sources for jsf/primefaces/ee-api/glassfish etc. to debug the behavior, so here's the answer:
component
:controller.method
) that causes redirect
datatable
datatable
generates its rows based on a @ViewScoped
beancontroller.method
invocation the @ViewScoped
bean that the datatable
depends on will be regenerated (with all its dependencies of course)Tested: In version 2.1.7
of JSF.
Looked in sources of 2.1.19
, and I'd expect same behavior there.
For those who cry out loud in lonely summer nights asking: "Why?"
POST
ed to the serverAPPLICATION_INVOCATION
rowEvent & clickEvent
UIViewRoot:794
javax.faces.UIData
The grandparent of org.primefaces.component.datatable.DataTable
backing p:datatable
starts processing the event @ UIData.broadcast(FacesEvent)
broadcast
method first saves the index of the last selected rowrowEvent
clickEvent
on the child UIComponent
, in our case on the Button
ActionListener.processAction(ActionEvent)
controller.method
which returns a redirect String
and things begin to go downhillredirectString
is processed by a NavigationHandler
ViewMap
removing all @ViewScoped
beans from it at line 179
. Which if we think about it is kind of logical, since we're on our way out.UIData.broadcast
which
302
) 4.3.1
@ViewScoped
bean(s) needed by the table get regenerated.THE END
Though I haven't tested I'd expect the same behavior h:datatable
, p:accordionPanel
, p:carousel
, p:galleria
, p:dataGrid
etc. In short every component that subclasses UIData
and doesn't provide a redirect
- aware broadcast
method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With