Here is my code,
search.xhtml page
<h:form id="searchform">
<h:inputText id="deptId" value="#{searchBean.departmentId}"></h:inputText>
<h:inputText id="deptName" value="#{searchBean.deparmentName}"></h:inputText>
<h:commandButton value="Click to Search" action="#{searchBean.searchEmployees}">
</h:commandButton>
</h:form>
searchresults.xhtml page
<rich:dataTable value="#{searchBean.employeeList}" var="e" id="table">
<rich:column>
<f:facet name="header">
<h:outputText value="FNAME"/>
</f:facet>
<h:outputText value="#{e.fName}"/>
</rich:column>
<rich:column>
<f:facet name="header">
<h:outputText value="LNAME"/>
</f:facet>
<h:outputText value="#{e.lName}"/>
</rich:column>
<rich:column>
<f:facet name="header">
<h:outputText value="DEPARTMENT"/>
</f:facet>
<h:outputText value="#{e.dept}"/>
</rich:column>
</rich:dataTable>
In the managed bean
ManagedBean
#ManagedBean(name="searchBean")
#RequestScoped
public class SearchBean implements Serializable{
private String departmentId;
private String deparmentName;
private List<EmpBean> employeeList;
//....get/set 's
public String searchEmployees(){
employeeList = service.getEmployees(departmentId,deparmentName);
return "searchresults.xhtml";
}
Issue: searchresults page is is not displaying records though it fetched records from table
I'm able to achieve this using search bean as session scope but i want to use the scope as Requestscope, bec of performance.
Please suggest...!
The Problem
The reason you're not seeing the results is because you have an incorrect understanding of the #RequestScope and consequently, improbable expectations of the scope
searchEmployees executes during the INVOKE_APPLICATION phase, the second to the last phase of the JSF request processing lifecycle. By the time the user is redirected to searchResults.xhtml, the instance of your SearchBean that holds the search results has been destroyed and a brand new one created, resulting in an empty list.
This is the rule for every bean scope except the #SessionScoped: a navigation action will cause the old bean to be destroyed and a new one created. This is not to say that #SessionScoped should be your scope of choice (it's generally a terrible idea to back a page with a #SessionScoped bean).
The Solution
Use the FlashScope to temporarily stash the results just for display on the other page. For example
employeeList = service.getEmployees(departmentId,deparmentName);
Flash theFlashScope = FacesContext.getCurrentInstance().getExternalContext().getFlash();
theFlashScope.put("searchResults",employeeList);
return "searchresults.xhtml";
Then in searchResults.xhtml
<rich:dataTable value="#{flash.searchResults}" var="e" id="table">
Here, #{flash} is an implicit EL object; you don't have to do anything else.
EDIT: Based on your "answer", you should be aware that the Flash object keeps variables stored in it for only the first render of the page. Subsequent HTTP requests will clear the content of the flash object.
If you're interested in keeping the content of the flash object beyond the first render, you should use the Flash#keep:
<rich:dataTable value="#{flash.keep.searchResults}" var="e" id="table">
Further Reading
Max Katz's blog on the Flash object
Related
I started using primafaces and I came up with the following scenario. The user rates and element and if the rating is valid then a span block appears or it hides depending the case. I am based on the example here: (http://www.primefaces.org/showcase/ui/input/rating.xhtml ) with the ajax approach. Note that a rate is valid if the user clicks on any star. So here's what I've done so far:
<h:form>
<p:panelGrid>
<p:row>
<p:column>
<p:rating value="#{searchBean.dateWeight}">
<p:ajax event="rate" listener="#{searchBean.addDatetoWeights}"
update="dates" render="dates" />
<p:ajax event="cancel"
listener="#{searchBean.removeDatefromWeights}"
update="dates" />
</p:rating>
<h:panelGroup id="dates" rendered="#{searchBean.dateRated}">
<h:outputText value="test"></h:outputText>
</h:panelGroup>
</p:column>
</p:row>
</p:panelGrid>
</h:form>
segment of the bean:
boolean dateRated;
int dateWeight;
public void addDatetoWeights(){
dateRated=true;
weights.put("date",dateWeight);
System.out.println(dateRated);
}
public void removeDatefromWeights(){
dateRated=false;
if(weights.containsKey("date"))
weights.remove("date");
}
Let's go back to the basics: HTML and JavaScript. It's important to also know them before diving into JSF. JSF is in the context of this question merely a HTML/JS code generator.
With <p:ajax update="dates"> you're basically telling JavaScript to grab the HTML element by the given ID and then replace its contents with the new contents retrieved from server in ajax response. However, as the <h:panelGroup id="dates"> is in first place never rendered to the HTML output, JavaScript can't find the element by document.getElementById() stuff in order to replace its contents and then just ignores the instruction.
Instead, the <p:ajax update="dates"> must refer a component which is always rendered, so that JavaScript can actually find it. Only its contents can be conditionally rendered.
Here's a rewrite:
<h:panelGroup id="dates">
<h:outputText value="test" rendered="#{searchBean.dateRated}" />
</h:panelGroup>
See also:
Why do I need to nest a component with rendered="#{some}" in another component when I want to ajax-update it?
I want to allow user to edit cells in data table only if some condition is met.
Initially I have tried <choose> to achieve this:
<p:dataTable var="item" value="${bean.items}" editable="true" editMode="cell">
<p:column headerText="column A">
<c:choose>
<c:when test="${item.isEditable}">
<p:cellEditor id="title">
<f:facet name="output">
<h:outputText value="#{item.title}"/>
</f:facet>
<f:facet name="input">
<p:inputText value="#{item.title}"/>
</f:facet>
</p:cellEditor>
</c:when>
<c:otherwise>
<h:outputText value="#{item.title}"/>
</c:otherwise>
</c:choose>
</p:column>
...
but it does not work. Another approach is to use rendered attribute:
<p:column headerText="column A">
<p:cellEditor rendered="${item.isEditable}">
<f:facet name="output">
<h:outputText value="#{item.title}"/>
</f:facet>
<f:facet name="input">
<p:inputText value="#{item.title}"/>
</f:facet>
</p:cellEditor>
<h:outputText value="#{item.title}" rendered="#{!item.isEditable}"/>
</p:column>
that works fine - user are able to edit only allowed cells.
But even if cell is not editable it still has ui-cell-editing class and looks like editable cell for user.
What is a correct way to apply condition to cell editing?
Thank you!
To properly learn the lesson of JSTL fail, it failed for the reason explained in the following answer: JSTL in JSF2 Facelets... makes sense? In a nutshell: #{item} isn't available at the moment JSTL runs.
Coming back to the concrete question: that style class is been inserted due to the combination editMode="cell" and the physical presence of <p:cellEditor> component in the <p:column>. The PrimeFaces datatable renderer isn't at all considering if the <p:cellEditor> is rendered or not. It just outright inserts the ui-editable-column style class which in turn triggers the ui-cell-editing style via JS/jQuery. You were looking in the right direction for the solution, JSTL which can conditionally physically add/remove JSF components in the JSF component tree, but unfortunately it won't work in this construct.
Your best bet is to post an issue report to the PrimeFaces guys whereby you ask to not only consider the physical presence of <p:cellEditor> component, but also its isRendered() outcome. Considering PrimeFaces version 3.5, that would be in line 796 of DataTableRenderer class which originally looks like this (newlines introduced for readability):
String styleClass = selectionEnabled
? DataTable.SELECTION_COLUMN_CLASS
: (column.getCellEditor() != null)
? DataTable.EDITABLE_COLUMN_CLASS
: null;
And should be modified as follows:
String styleClass = selectionEnabled
? DataTable.SELECTION_COLUMN_CLASS
: (column.getCellEditor() != null && column.getCellEditor().isRendered())
? DataTable.EDITABLE_COLUMN_CLASS
: null;
If you can't wait, in the meanwhile you could homegrow a custom renderer.
package com.example;
import org.primefaces.component.datatable.DataTableRenderer;
public class MyDataTableRenderer extends DataTableRenderer {
#Override
protected void encodeCell(FacesContext context, DataTable table, UIColumn column, String clientId, boolean selected) throws IOException {
// Copypaste here the original encodeCell() source code and make modifications where necessary.
}
}
Then, to get it to run, register it as follows in faces-config.xml:
<render-kit>
<renderer>
<description>Overrides the PrimeFaces table renderer with customized cell renderer.</description>
<component-family>org.primefaces.component</component-family>
<renderer-type>org.primefaces.component.DataTableRenderer</renderer-type>
<renderer-class>com.example.MyDataTableRenderer</renderer-class>
</renderer>
</render-kit>
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
I'm using primefaces commandLink in p:datatable and when user clicks on link. It's supposed to navigate to another page including specific info of object that is chosen from table. I don't use any ajax tags. Problem is when first time clicks on link it doesn't invoke action actually nothing happens and on second click it works. Here is my code :
JSF with Datatable
<h:form>
<h:outputText value="Nothing is found" rendered="#{searchView.citizenSearchList.rowCount==0}"/>
<p:dataTable var="cust" value="#{searchView.citizenSearchList}" dynamic ="true" paginator="true" rows="5" paginatorAlwaysVisible="false" style="width: 700">
<p:column>
<f:facet name ="header">
<h:outputText value="name "/>
</f:facet>
<h:outputText value="#{cust.name}"/>
</p:column>
<p:column>
<f:facet name ="header">
<h:outputText value="lastname "/>
</f:facet>
<h:outputText value="#{cust.citizenList.get(0).lastname}"/>
</p:column>
<p:column>
<f:facet name ="header">
<h:outputText value="Id "/>
</f:facet>
<h:outputText value="#{cust.registernumber}"/>
</p:column>
<p:column>
<f:facet name ="header">
</f:facet>
<p:commandLink value="See" action="#{customerView.prepareCitizenView()}"/>
</p:column>
</p:dataTable>
</h:form>
ManagedBean: customerView's action method
#ManagedProperty(...)
SearchView searchview;
public String prepareCitizenView(){
this.customer = (Customer) searchview.citizenSearchResultList.getRowData();
if(this.customer != null)
return "citizeninfo";
else
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "no data.", "no data"));
return null;
}
ManagedBean: searchView
DataModel citizenSearchResultList;
public DataModel getCitizenSearchResultList() {
return citizenSearchResultList;
}
You can return redirect to same page.
customerView.prepareCitizenView can retruns same page with redirect.
like
return "citizeninfo.jsf?faces-redirect=true";
this "jsf" changes according to what you use
As mehmet cinar stated, the solution is to use a redirect in your navigation outcome. I've had this problem myself.
return "citizeninfo.jsf?faces-redirect=true";
From what I was able to deduce, the reason is that the ajax submit will not contain a ViewState request parameter for the new page. Without the ViewState the first time, things break.
Once you perform a redirect, the redirect will correctly have a Viewstate parameter appended to the request, and buttons can be clicked the first time
If p:commandLink is included within two h:form then action will be invoked on second call.
Check the outer tags of p:commandLink
i m using JSF2.0 and i m making one dataTable in that datatable i m getting the value from managed bean.And in managed bean in post construct annoted method i m calling my web service from another file.
Following is code for that
<h:dataTable
value="#{bean1.getList}" var="c" styleClass="order-table"
headerClass="order-table-header" width="100%"
rowClasses="order-table-odd-row,order-table-even-row" rows="8"
columnClasses="first,second">
<h:column>
<f:facet name="header">
<h:selectBooleanCheckbox></h:selectBooleanCheckbox>
</f:facet>
<h:selectBooleanCheckbox value="#{c.id}"></h:selectBooleanCheckbox>
</h:column>
<h:column>
<!-- <f:facet name="header"/> -->
<h:outputLabel value="From: "></h:outputLabel>
<h:outputLabel value="#{c.from}"></h:outputLabel>
<br></br>
<!-- -->
<h:outputLabel value="Sub: "></h:outputLabel>
<h:outputLabel value="#{c.sub}"/>
<h:commandLink immediate="true" action="#{bean2.doRead}" value="Read" id="Read"></h:commandLink>
</h:column>
<!-- Footer Setting -->
<f:facet name="footer">
</f:facet>
</h:dataTable>
My Bean1 class
#PostConstruct
public void prepareList(){
{
web service call
}
public List<InboxBean> getemailList(){
return list;
}
Now when i m clicking on commandlink which has id Read at that time my bean1 post construct taged property also called. That i dont want to perform. So,how to get out from this problem and i also want to set the subject value in bean2 setProperty. Thanks in advance
That can happen if the bean is put in request scope. Every single HTTP request will then reconstruct the bean. Put the bean in view or session scope instead.
E.g. in the view scope:
#ManagedBean
#ViewScoped
public class Bean {}
A view scoped bean lives as long as you're interacting with the same view by returning null or void in action methods.
Or in the session scope:
#ManagedBean
#SessionScoped
public class Bean {}
A session scoped bean lives as long as the established browser session. That is, from the very first HTTP request involving the bean until the client closes the entire browser instance or when the session expires on the server side (which defaults to 30 minutes).
For your particular case, a view scoped bean is most likely the best choice.
See also:
How to choose the right bean scope?