Primefaces 8.0 Datatable with Dynamic Model and Columns - datatable

I have a primefaces dataTable that displays data from several database tables. A selection list allows the user to select the specific database table to display. It works as expected except when the dataTable filtering capability is used. For example, when a user selects 'DEPT' from the selection list, the dataTable is rendered with data from the DEPT table. The user can select other tables normally. However, if the user selects another table called 'EMP' after filtering, the dataTable fails to render with the following exception:
javax.el.PropertyNotFoundException: The class 'example.dto.Dept' does not have the property 'firstName'.
at javax.el.BeanELResolver.getBeanProperty(BeanELResolver.java:576)
at javax.el.BeanELResolver.getValue(BeanELResolver.java:291)
at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:156)
Here's the .xhtml file:
<h:form prependId="false">
<p:outputLabel for="selTbl" value="Select a table:" />
<p:autoComplete id="selTbl" value="#{mainBean.selectedTable}"
completeMethod="#{mainBean.filterAuditTables}" cache="true" dropdown="true" effect="fade"
minQueryLength="3" forceSelection="true" size="35" style="margin-left: 10px;">
<p:ajax event="itemSelect" listener="#{mainBean.onTableSelect}" process="#this" update="#form" />
</p:autoComplete>
<p:dataTable id="audTblData" value="#{mainBean.data}" var="row"
filteredValue="#{mainBean.filteredData}" resizableColumns="true" resizeMode="expand"
sortMode="multiple">
<f:facet name="header">
<h:outputText value="#{mainBean.selectedTable}" />
</f:facet>
<p:columns value="#{mainBean.tableColumns}" var="col" sortBy="#{row[col.property]}"
filterBy="#{row[col.property]}" filterMatchMode="contains">
<f:facet name="header">
<h:outputText value="#{col.header}" />
</f:facet>
<h:outputText value="#{row[col.property]}" />
</p:columns>
</p:dataTable>
</h:form>
MainBean.java:
#Named
#ViewScoped
public class MainBean implements Serializable {
private static final long serialVersionUID = 1L;
// these are used for the audited table selection list
private List<String> auditedTables;
private String selectedTable;
// these are used in the table that displays the audit data
private List<ColumnModel> tableColumns;
private List<Auditable> data;
private List<Auditable> filteredData;
#Inject
private AudviewService audviewService;
#PostConstruct
public void init() {
auditedTables = audviewService.getAuditedTables();
}
public List<String> filterAuditTables(String query) {
return auditedTables
.stream()
.filter(t -> t.contains(query.toUpperCase()))
.collect(Collectors.toList());
}
public void onTableSelect(SelectEvent<String> event) {
retrieveTableData();
}
public void retrieveTableData() {
List<String> columns = audviewService.listTableColumns(selectedTable);
// initialize columns for <p:dataTable>
tableColumns = new ArrayList<ColumnModel>();
for (String col : columns) {
tableColumns.add(new ColumnModel(col, AudviewUtil.columnToProperty(col)));
}
// retrieve data for the selected table
data = audviewService.getTableData(selectedTable);
}
/* getters and setters */
}
Note that Auditable is an interface implemented by Dept.java and Emp.java.

As you noticed, the problem is switching from a filtered or sorted datatable to another, if the filtered or sorted column is a field that isn't in the new selected class. An easy solution would be moving all the needed fields into the superclass Auditable.
Another approach is separating datatable resetting&updating in two steps, here a possible solution (I replace, for testing purpose, your service with static code, so there could be some errors adapting my solution to your code):
xhtml
<h:form id="formTbl" prependId="false">
<p:outputLabel for="selTbl" value="Select a table:" />
<p:autoComplete id="selTbl" value="#{mainBean.selectedTable}"
completeMethod="#{mainBean.filterAuditTables}" cache="true"
dropdown="true" effect="fade" minQueryLength="3"
forceSelection="true" size="35" style="margin-left: 10px;">
<p:ajax event="itemSelect" listener="#{mainBean.onTableSelect}"
process="#this" onstart="PF('vtWidget').clearFilters()" />
</p:autoComplete>
<p:remoteCommand name="btn" process="#this" update="audTblData" />
<p:dataTable id="audTblData" value="#{mainBean.data}" var="row"
filteredValue="#{mainBean.filteredData}" resizableColumns="true"
resizeMode="expand" sortMode="multiple" widgetVar="vtWidget">
<f:facet name="header">
<h:outputText value="#{mainBean.selectedTable}" />
</f:facet>
<p:columns value="#{mainBean.tableColumns}" var="col"
sortBy="#{row[col.property]}" filterBy="#{row[col.property]}"
filterMatchMode="contains">
<f:facet name="header">
<h:outputText value="#{col.header}" />
</f:facet>
<h:outputText value="#{row[col.property]}" />
</p:columns>
</p:dataTable>
</h:form>
java
public void retrieveTableData() {
List<String> columns = listTableColumns(selectedTable);
// initialize columns for <p:dataTable>
tableColumns = new ArrayList<ColumnModel>();
for (String col : columns) {
tableColumns.add(new ColumnModel(col + " header", col));
}
// retrieve data for the selected table
data = getData(selectedTable);
DataTable dataTable = (DataTable) FacesContext.getCurrentInstance().getViewRoot().findComponent("formTbl:audTblData");
if (dataTable != null) {
dataTable.reset();
}
PrimeFaces.current().executeScript("btn()");
}
Pay attention, if you need also to manage pagination.

Related

Update single row in JSF / Primefaces datatable using AJAX

How could I update a single row in a p:datatable when using AJAX?
I don't want to update the whole datatable because it has a lot of rows and it's going to take some time..
My layout:
<h:form id="visitForm">
<p:dataTable id="visitTable" var="visit" value="#{visitBean.findAllVisits()}">
<p:column headerText="${msgs['email']}"
<h:outputText value="#{visit.contactDetail.email}"/>
</p:column>
<p:column headerText="${msgs['clearance']}" id="clearance">
<p:commandButton value="${msgs['clearance.ok']}" actionListener="#{visitBean.makeClearanceNotOk(visit)}"/>
</p:column>
</p:dataTable>
</h:form>
I've tried out some things like update = "clearance" etc but it doesn't seem to work.
I'm using JSF 2.1 and Primefaces 5.2
You can use #row(n) search expression which does just that - it updates the nth row in a table. In order to update the current row, you need to pass row index as an argument. Set rowIndexVar="rowIdx" attribute on <p:dataTable> and then:
<p:commandButton ... update="#form:visitTable:#row(#{rowIdx})" />
Not sure if I'm late for the party but let me give my 5 cents on this subject on how to update content of a row using just plain ajax features from PrimeFaces.
1) Partial update: My first approach to update something in a specific row using PF is not exactly update the whole row, but update the regions of interest inside the row. This can be achieved by just defining the holding panels and updating them. For example:
<h:form id="testForm">
<p:dataTable id="myEntityTable" var="myEntity" value="#{myController.allEntities}">
<p:column headerText="id">
<h:outputText value="#{myEntity.id}"/>
</p:column>
<p:column headerText="last update">
<p:outputPanel id="lastUpdatePanel">
<h:outputText value="#{myEntity.lastUpdate}">
<f:convertDateTime pattern="HH:mm:ss" type="date" />
</h:outputText>
</p:outputPanel>
</p:column>
<p:column headerText="counter">
<p:outputPanel id="counterPanel">
<h:outputText value="#{myEntity.counter}"/>
</p:outputPanel>
</p:column>
<p:column headerText="increment">
<p:commandButton value="+"
actionListener="#{myController.increment(myEntity)}"
update="counterPanel, lastUpdatePanel"/>
</p:column>
</p:dataTable>
</h:form>
The trick is to update the target panels (in this example the fragment update="counterPanel, lastUpdatePanel"). This results in something like the following image:
2) Actually updating the row: Very often the previous approach works fine enough. However, if it is really needed to update the row one can follow the advice given in one of the previous answers and use the #row keyword:
<h:form id="testForm">
<p:dataTable id="myEntityTable" var="myEntity" value="#{myController.allEntities}" rowIndexVar="rowIndex">
<p:column headerText="id">
<h:outputText value="#{myEntity.id}"/>
</p:column>
<p:column headerText="last update 1">
<p:outputPanel>
<h:outputText value="#{myEntity.lastUpdate}">
<f:convertDateTime pattern="HH:mm:ss" type="date" />
</h:outputText>
</p:outputPanel>
</p:column>
<p:column headerText="last update 2">
<h:outputText value="#{myEntity.lastUpdate}">
<f:convertDateTime pattern="HH:mm:ss" type="date" />
</h:outputText>
</p:column>
<p:column headerText="counter">
<p:outputPanel>
<h:outputText value="#{myEntity.counter}"/>
</p:outputPanel>
</p:column>
<p:column headerText="increment">
<p:commandButton value="+"
actionListener="#{myController.increment(myEntity)}"
update="#form:myEntityTable:#row(#{rowIndex})"/>
</p:column>
</p:dataTable>
</h:form>
The trick is to hold each content from the columns inside a p:outputPanel and let update="#form:myEntityTable:#row(#{rowIndex})" make the job. I consciously leave the "last update 2" column without an outputPanel in order to illustrate this point:
Hence, whereas the columns "last update 1" and "counter" actually update after a click in "+" the "last update 2" column keeps unchanged. So, if you need to update a content, wrap up it with an outputPanel. It is noteworthy as well that the outputPanels holding each column content don't need an explicit id (you can add one if you want).
In the sake of completeness, in these examples I have used PF 6.2. The backbean is pretty straightforward:
package myprefferedpackage;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class MyController {
private List<MyEntity> entities;
#PostConstruct
public void init() {
this.entities = new ArrayList<MyEntity>(10);
for(int i = 0; i < 10; ++i) {
this.entities.add(new MyEntity(i));
}
}
public List<MyEntity> getAllEntities() {
return entities;
}
public void increment(MyEntity myEntity) {
myEntity.increment();
}
public class MyEntity {
private int id;
private int counter;
private Date lastUpdate;
public MyEntity(int id) {
this.id = id;
this.counter = 0;
this.lastUpdate = new Date();
}
public void increment() {
this.counter++;
this.lastUpdate = new Date();
}
public int getId() {
return id;
}
public int getCounter() {
return counter;
}
public Date getLastUpdate() {
return lastUpdate;
}
}
}
Either use the 'ajax' functionality of a utility library like OmniFaces or be creative with the PrimeFaces Selectors.
In both cases you need to get access to the e.g. the 'current' row or rowId. But since that you have the buttons IN the row, that should not be a problem. I unfortunately don't have the time to create examples for you
I try with uptate = "#parent:componentAnotherColumn" and works. Only update the same row
<p:column>
<p:selectBooleanCheckbox value="#{atributoVar.booleanValue}">
<p:ajax process="#this" update="#parent:componentAnotherColumn"/>
</p:selectBooleanCheckbox>
</p:column>
<p:column>
<p:selectBooleanCheckbox id="componentAnotherColumn" value="#{!atributoVar.booleanValue}"/>
</p:column>

Add Dynamic Row in <p:datatable> Using <p:commandButto> and <f:ajax>

in following code commandbutton not properly work for the datatable.
<p:dataTable id="invoiceTable" var="ipsDetail"
value="#{invoiceBean.ipsDetails}" border="1">
<p:column headerText="Sr. No.">
<h:inputText id="serialN7umber" value="#{ipsDetail.serialNumber}"
size="3" />
</p:column>
<p:column headerText="Description of Goods">
<p:inputText value="#{ipsDetail.descriptionOfGoodsOrService}" />
</p:column>
<p:column headerText="HSN Code">
<p:inputText value="#{ipsDetail.hsnCode}" styleClass="Alingment" />
</p:column>
<p:column headerText="Quantity">
<p:inputText value="#{ipsDetail.quantity}" styleClass="Alingment" />
</p:column>
<p:column headerText="Rate">
<p:inputText value="#{ipsDetail.rate}" styleClass="Alingment" />
</p:column>
<p:column headerText="Percentage Discount">
<p:inputText value="hello" rendered="#{ipsDetail.percentDiscount}"
styleClass="Alingment" />
</p:column>
<p:column headerText="Amount">
<p:inputText value="#{invoiceBean.amount}" styleClass="Alingment" />
</p:column>
<f:facet name="footer">
<p:commandButton value="Add New Row" action="#{invoiceBean.addRow}" update=":form:invoiceTable">
<!-- <f:ajax execute=":form:invoiceTable" render=":invoiceTable:addColumn" /> -->
</p:commandButton>
</f:facet>
</p:dataTable>
</h:form>
I want To add dynamic row with inputtext using primefaces commandbutton in java. it work but re-render not possible.
public class InvoiceBean implements Serializable {
public List getInvoices() {
InvoiceDao invoiceDao = new InvoiceDao();
invoices = invoiceDao.getInvoiceData();
return invoices;
}
public void setInvoices(List<Invoice> invoices) {
if (invoices != null) {
this.invoices.add(new Invoice());
}
}
public void getInvoiceData() {
InvoiceDao invoiceDao = new InvoiceDao();
ipsDetail = new InvoiceProductsServicesDetail();
if ( ipsDetail != null) {
ipsDetail
.setDescriptionOfGoodsOrService(descriptionOfGoodsOrService);
ipsDetail.setHsnCode(hsnCode);
ipsDetail.setInvoiceId(invoice.getId());
ipsDetail.setPercentDiscount(percentDiscount);
ipsDetail.setQuantity(quantity);
ipsDetail.setRate(rate);
ipsDetail.setSerialNumber(serialNumber);
ipsDetail.setServiceTax((float) 12.5);
ipsDetail.setVat(5);
System.out.println("InvoiceBean.insertInvoice");
}
invoiceDao.insertInvoice(invoice, ipsDetail);
}
public Row addRow() {
Row row = new Row();
InputText inputText = new InputText();
inputText.setSubmittedValue("Hello");
Column column = new Column();
row.setParent(inputText);
column.setHeader(inputText);
column.setHeaderText("Hardik");
return row;
}
}
This Is code for add row or column with inputtext
Since you are using Primefaces you can also Update any component from ManagedBean itself using org.primefaces.context.RequestContext object.
For example:
Facelet:
<h:form id="form1">
<p:dataTable id="myTab">
...
</p:dataTable>
</h:form>
ManagedBean:
RequestContext reqCtx = Requestcontext.getCurrentInstance();
req.Ctx.update("form1:myTab");
You can't update the table from inside the table. You can do the following:
<p:dataTable id="invoiceTable" var="ipsDetail" value="#{invoiceBean.ipsDetails}"
border="1">
...
<f:facet name="footer">
<p:commandButton value="Add New Row" onclick="updateTable();">
</p:commandButton>
</f:facet>
</p:dataTable>
...
<p:remoteCommand name="updateTable" update=":form:invoiceTable"
actionListener="#{invoiceBean.addRow}" />
Thank For Your Response and Solution regarding my question is below edit addRow().
public void addRow() {
ipsDetail = new InvoiceProductsServicesDetail();
if (descriptionOfGoodsOrService != null
&& hsnCode != null && quantity != 0 && rate != 0) {
ipsDetail.setSerialNumber(serialNumber);
ipsDetail
.setDescriptionOfGoodsOrService(descriptionOfGoodsOrService);
ipsDetail.setHsnCode(hsnCode);
ipsDetail.setPercentDiscount(percentDiscount);
ipsDetail.setQuantity(quantity);
ipsDetail.setRate(rate);
ipsDetails.add(ipsDetail);
}
FacesContext facesContext = FacesContext.getCurrentInstance();
try {
DataTable table = (DataTable) facesContext.getViewRoot()
.findComponent("form:invoiceTable");
UIComponent uiTable = ComponentUtils.findParentForm(facesContext,
table);
final AjaxBehavior behavior = new AjaxBehavior();
RowEditEvent rowEditEvent = new RowEditEvent(uiTable, behavior,
table.getRowData());
rowEditEvent.setPhaseId(PhaseId.UPDATE_MODEL_VALUES);
table.broadcast(rowEditEvent);
} catch (AbortProcessingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

<p:ajax> Unable to attach <p:ajax> to non-ClientBehaviorHolder parent

I use JSF 2 , primefaces 4.0 and i try to use DataTable - In-Cell Editing as it's produced in primefaces showcase, but i have an error althought i copied the same example shown in showcase
the error is
<p:ajax> Unable to attach <p:ajax> to non-ClientBehaviorHolder parent
this is the xhtmlpagecode
<rich:panel style="width : 800px; height : 551px; " >
<f:facet name="header" >
<h:outputText value="Tableau des articles" align="center" style="FONT-SIZE: small;"/>
</f:facet>
<h:form id="form">
<p:dataTable id="cars" var="car" value="#{articlesbean.LMatpilotaccess1}" editable="true" editMode="cell" widgetVar="carsTable">
<f:facet name="header">
Matériel du pilotage et accessoires
</f:facet>
<p:growl id="messages" showDetail="true"/>
<p:contextMenu for="cars" widgetVar="cMenu">
<p:menuitem value="Edit Cell" icon="ui-icon-search" onclick="PF('carsTable').showCellEditor();return false;"/>
<p:menuitem value="Hide Menu" icon="ui-icon-close" onclick="PF('cMenu').hide()"/>
</p:contextMenu>
<p:column headerText="Serie" style="width:25%">
<p:ajax event="cellEdit" listenner="#{articlesbean.onCellEdit}" update=":form:messages" />
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{car.serie}" /></f:facet>
<f:facet name="input"><p:inputText id="modelInput" value="#{car.serie}" style="width:96%"/></f:facet>
</p:cellEditor>
</p:column>
</p:dataTable>
</h:form>
</rich:panel>
and this is my bean
#ManagedBean(name="articlesbean")
#ViewScoped
public class ArticlesBean implements Serializable{
#Inject
private ArticlesDAO articleDAO;
#Inject
private Matpilotaccess1 matpilotaccess1;
#Inject
private Matpilotaccess2 matpilotaccess2;
#Inject
private Poteaux poteaux ;
#Inject
private Travgc1 travgc1;
#Inject
private Travgc2 travgc2;
#Inject
private Travresurbain travresurbain;
private List LMatpilotaccess1 = new ArrayList();
private List LMatpilotaccess2 = new ArrayList();
private List LPoteaux = new ArrayList();
private List LTravgc1 = new ArrayList();
private List LTravgc2 = new ArrayList();
private List LTravresurbain = new ArrayList();
public void onCellEdit(CellEditEvent event) {
Object oldValue = event.getOldValue();
Object newValue = event.getNewValue();
if(newValue != null && !newValue.equals(oldValue)) {
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Cell Changed", "Old: " + oldValue + ", New:" + newValue);
FacesContext.getCurrentInstance().addMessage(null, msg);
}
}
//// Getters and setters
You nested the <p:ajax> inside a <p:column>. The <p:ajax> requires to be nested in a component implementing the ClientBehaviorHolder interface. However, the Column component class behind <p:column> does not implement it. The DataTable component class behind <p:dataTable> implements it.
You should be nesting <p:ajax> inside <p:dataTable> instead:
<p:dataTable ...>
<p:ajax ... />
<p:column ...>
...
</p:column>
</p:dataTable>
Exactly as demonstrated on their showcase site. In other words, your statement
althought i copied the same example shown in showcase
is actually not true.

Navigate to another page on rowselect of datatable in primefaces

I have a primefaces datatable where number of records are displaying.
I want navigate to another page on the rowSelect event (to edit the selected entity for example).
The closest sample/demo I could find was use the p:ajax tag to bind the rowSelect event to a listener method
http://www.primefaces.org/showcase-labs/ui/datatableRowSelectionInstant.jsf
I also got one article for the same http://forum.primefaces.org/viewtopic.php?f=3&t=14664
, I tried to implement in same as they did.But it also didn't worked.
I am trying in this way and guide me If I missed anything.
<p:dataTable var="product" value="#{addPatientBB.patientAddList}" paginator="true" rows="10"
selection="#{addPatientBB.pat}" selectionMode="single">
<p:ajax event="rowSelect" listener="#{addPatientBB.onRowSelect}" />
<p:column>
<f:facet name="header">
<h:outputText value="FirstName" />
</f:facet>
<h:outputText value="#{product.firstName}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Email" />
</f:facet>
<h:outputText value="#{product.email}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Gender" />
</f:facet>
<h:outputText value="#{product.gender}" />
</p:column>
</p:dataTable>
And Backing bean is :
#ManagedBean
#ViewScoped
public class AddPatientBB implements Serializable
{
private Patient pat;
public Patient getPat()
{
System.out.println("tried to get pat");
return pat;
}
public void setPat(Patient pat)
{
this.pat = pat;
System.out.println("tried to set pat");
}
public void onRowSelect()
{
System.out.println("inside onRow select Method");
ConfigurableNavigationHandler configurableNavigationHandler = (ConfigurableNavigationHandler) FacesContext.getCurrentInstance().getApplication().getNavigationHandler();
System.out.println("navigation objt created");
configurableNavigationHandler.performNavigation("Page?faces-redirect=true");
// Page is my navigation page where I wish to navigate named as
// "Page.xhtml"
System.out.println("Navigation executed");
}
}
So how can I navigate to another page on rowselect event? and how can display its values after navigationg the form.
I am able to go inside onRowSelect() method , actually problem is he is not able to get or understood that path :
configurableNavigationHandler.performNavigation("Page?faces-redirect=true");
so he is not able to print any logs after this line.
why is it so? is it because of I am using Liferay?
Pla guide me.
Well i think the onRowSelect is never executed because you defined it wrong.
Try this:
public void onRowSelect(SelectEvent event)
{
FacesContext.getCurrentInstance().getExternalContext().redirect("page.xhtml?id=" +pat.getId());
}
If u are using FacesServlet then use.jsf instead of .xhtml
public void onRowSelect(SelectEvent event)
{
FacesContext.getCurrentInstance().getExternalContext().redirect("page.jsf?id="+pat.getId());
}

DataTable Order by column erase values

I have PrimeFaces dataTable that is been filled by a Ajax call.
When I click on a column title, to order its values, the values disappear.
<p:commandButton value="Pesquisar" actionListener="#{requestController.listRequests}" update="dataTable" />
Here is my view:
<p:dataTable id="dataTable" var="order" value="#{requestController.backing.requestsList}"
paginator="true" rows="10"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink}">
<p:column sortBy="#{order.companyRequest}">
<f:facet name="header">
<h:outputText value="Pedido" />
</f:facet>
<h:outputText value="#{order.companyRequest}" />
</p:column>
<p:column sortBy="#{order.company.companyName}">
<f:facet name="header">
<h:outputText value="Cliente" />
</f:facet>
<h:outputText value="#{order.company.companyName}" />
</p:column>
<p:column sortBy="#{order.emissionDate}">
<f:facet name="header">
<h:outputText value="Data" />
</f:facet>
<h:outputText value="#{order.emissionDate}">
<f:convertDateTime pattern="dd/MM/yyyy"/>
</h:outputText>
</p:column>
<p:column sortBy="#{order.requestSituation.description}">
<f:facet name="header">
<h:outputText value="Status" />
</f:facet>
<h:outputText value="#{order.requestSituation.description}" />
</p:column>
<p:column>
<f:facet name="header">
</f:facet>
<h:form>
<h:commandLink value="Detalhes"/>
</h:form>
</p:column>
</p:dataTable>
EDIT
RequestController
#ManagedBean
#RequestScoped
public class RequestController implements Serializable
{
private RequestBacking backing;
public RequestController()
{
backing = new RequestBacking();
}
public void changeEventListener(ValueChangeEvent e)
{
backing.requestSearchType = e.getNewValue().toString();
}
public void change()
{
switch (backing.requestSearchType)
{
case "data":
backing.mask = "99/99/9999";
backing.maskSize = "10";
break;
case "cnpj":
backing.mask = " 99.999.999/9999-99";
backing.maskSize = "20";
break;
default:
backing.mask = "";
backing.maskSize = "50";
}
}
public void listRequests() throws ParseException
{
CompanyVO companyVO = new CompanyVO();
switch (backing.requestSearchType)
{
case "cnpj":
companyVO.setCnpj(backing.requestSearchValue);
break;
case "cliente":
companyVO.setCompanyName(backing.requestSearchValue);
break;
case "pedido":
backing.requestVO.setCompanyRequest(Integer.parseInt(backing.requestSearchType));
break;
}
SupplierVO supplierVO = new Support().getUserSession().getSupplier();
backing.requestVO.setEmissionDate(new Support().convertDate(backing.requestSearchValue));
backing.requestVO.setSupplier(supplierVO);
backing.requestVO.setCompany(companyVO);
backing.requestsList = new ArrayList<>(backing.getBo().getRequest(backing.requestVO));
if (backing.requestsList.isEmpty())
{
FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_WARN, "Nenhum registro encontrado!", null);
FacesContext.getCurrentInstance().addMessage(null, facesMessage);
backing.requestsList = null;
}
}
..backing getter and setter
}
My requestsList is on my RequestBacking where I have all my getters and setters, please correct me if there is a better way of doing this, I'm using it because it leaves my controller cleaner.
public List<RequestVO> requestsList;
Apparently the value="#{requestController.backing.requestsList}" didn't return the same value as it did on the initial request. That can happen if it's a request scoped bean and/or if the requestsList is populated on every request based on a request based variable.
That's just a design mistake. Put the managed bean in the view scope and make sure that you aren't doing any business logic in a getter method. The nested class backing is also suspicious or it must be a poor naming.
See also:
Why JSF calls getters multiple times
How to choose the right bean scope?
Update in a nutshell, your bean should look something like this:
#ManagedBean
#ViewScoped
public class Orders {
private String query; // +getter +setter
private List<Order> results; // +getter (no setter required)
#EJB
private OrderService service;
public void search() {
results = service.search(query);
}
// Add/generate normal getters/setters (don't change them!)
}
and your view should look like this:
<h:form>
<p:inputText value="#{orders.query}" />
<p:commandButton value="Search" action="#{orders.search}" update=":tableForm" />
</h:form>
<h:form id="tableForm">
<p:dataTable value="#{orders.results}" var="order" ... rendered="#{not empty orders.results}">
...
</p:dataTable>
<h:outputText value="No results found" rendered="#{facesContext.postback and empty orders.results}" />
</h:form>

Resources