JSF reload the same function several times - jsf

I have a problem with JSF.
I make a page with JSF and dataTable of primefaces, but I realized that when I use a var into datatable, JSF reload a same get method many times.
I don't know if because the JSF or my Program, someone can help me?
<p:dataTable var="Usuario" value="#{usuarioBean.listaUsuario}"
paginator="true" rows="10" selection="#{usuarioBean.usuario}"
rowKey="#{Usuario.id}"
id="dataTable"
paginatorPosition="bottom">
<p:column headerText="ID" style="width: 10px">
<h:outputText value="#{Usuario.id}"/>
</p:column>
<p:column headerText="Nome">
<h:outputText value="#{Usuario.nome}"/>
</p:column>
<p:column headerText="E-mail">
<h:outputText value="#{Usuario.email}"/>
</p:column>
<p:column headerText="Telefone" style="width: 10px">
<h:outputText value="#{Usuario.telefone}"/>
</p:column>
<p:column headerText="Editar" style="width: 10px;">
<p:commandLink id="btnEditar" action="#{usuarioBean.ChamareditarUsuario()}" ajax="false" title="Editar">
<h:graphicImage value="/resources/img/editar.png" style="position: relative; top: 25%; left: 25%;" />
<f:setPropertyActionListener value="#{Usuario}" target="#{usuarioBean.usuario}" />
</p:commandLink>
</p:column>
<p:column headerText="Excluir" style="width: 10px;">
<p:commandLink id="btnDeletar" title="Deletar" action="#{usuarioBean.deletarUsuario()}" update="dataTable">
<h:graphicImage value="/resources/img/deletar.png" style="position: relative; top: 25%; left: 25%;"/>
<f:setPropertyActionListener value="#{Usuario}" target="#{usuarioBean.usuario}" />
</p:commandLink>
</p:column>
<p:column selectionMode="single" width="1%"/>
</p:dataTable>
#ManagedBean
#RequestScoped
public class UsuarioBean {
private Usuario usuario = new Usuario();
private String campo;
private String valor;
private List<Usuario> listaUsuario;
private String acesso;
private List<Acesso> listaAcesso;

You can understand a little more in this question:
Why JSF calls getters multiple times
Basiclly, a getter is called several times, is part of the JSF lifecycle.
Cheers.

Show your usuarioBean - what Scope does it have?
If it has no Scope (or the wrong scope), the bean will be reconstructed, every time you access #usuarioBean.listaUsuario- which will happen 4 times per iteration in your example.
To avoid that, make it #RequestScoped, so it lives as long as the current Request.
Sidenode: h:datatable is not the primefaces component. it would be p:datatable with the right Namespace imported.

Related

Can't filter using backing bean

I'm trying to filter a column using backing bean function.
<p:dataTable id="cars"
var="car"
value="#{manageAllCoursesBean.courses}"
filteredValue="#{manageAllCoursesBean.filteredCourse1}">
<f:facet name="header">
<p:outputPanel>
<p:inputText id="globalFilter"
onkeyup="PF('carsTable1').filter()"
style="width:250px"
placeholder="Entrer un mot clé"/>
</p:outputPanel>
</f:facet>
<p:column headerText="Name"
filterBy="#{car.name}"
sortBy="#{car.name}"
style="color: #400040; font-size: 10px; width: 150px; text-align:center">
<h:outputText value="#{car.name}" />
</p:column>
<p:column headerText="Teacher"
filteredBy="#{manageAllCoursesBean.findTeacherByIdCourse(car.id)}"
sortBy="#{manageAllCoursesBean.findTeacherByIdCourse(car.id)}"
style="color: #400040; font-size: 10px; width: 175px; text-align:center">
<h:outputText value="#{manageAllCoursesBean.findTeacherByIdCourse(car.id)}" />
</p:column>
</p:dataTable>
the backing bean method is:
public String findTeacherByIdCourse(String courseId) throws IOException
{
return serviceManager.findTeacherByCourseId(courseId);
}
the filter with Name is working as well.
However, is not the case with Teacher.
Have you please any idea about solving that ?.
Big thanks.
As described on Primefaces showcase, there's no way to use managed bean method with filterBy under p:column.
I proposed that solution:
You can convert your entity Course to a courseModel and then add teachers as a list of strings.
then in your managed bean will be :
List<CourrierModel> lacmss = new ArrayList<CourrierModel>();
DataModel allDatasAssociatedCE = new ListDataModel();
//...
allDatasAssociatedCE.setWrappedData(lacmes);
for(Course c: courses)
{
CourseModel cme = new CourseModel();
cme.setCourse(c);
cme.setTeachers(findTeacherByIdCourse(c));
lacmss.add(cme);
}
HTH.

Primefaces action is not fired in datagrid

I have the following Primefaces 3.5 page where I defined two commandLink. My problem is that action of lockout is not fired (checked with breakpoint) although lockoutTest with the same setting works. oncomplete works on both commandLink No exception is thrown.
<p:dataTable id="calendar" value="#{calendarView.calendarData.entrySet().toArray()}" var="row">
<f:facet name="header">
<p:panelGrid>
<p:row>
<p:column>
<p:commandLink id="lockoutTest"
value="test lockout"
update=":mainForm:lockoutEditorDialog"
process="#this"
action="#{calendarView.editLockout(15,15)}"
oncomplete="lockoutDialogWidget.show()">
<f:attribute name="title" value="valami" escape="true" />
</p:commandLink>
</p:column>
</p:row>
</p:panelGrid>
</f:facet>
<p:column style="width: 50px; text-align: right">
<f:facet name="header">
<h:outputText value="#{msgs.calendar_room}" />
</f:facet>
<h:outputText value="#{row.key.roomNumber}" />
</p:column>
<p:columns value="#{calendarView.columns}" var="column" style="text-align: center; #{not empty row.value[column].color ? 'background-color:#'.concat(row.value[column].color):''}">
<f:facet name="header">
<h:outputText value="#{column}" />
</f:facet>
<p:commandLink id="lockout"
value="#{row.value[column].text}"
update=":mainForm:lockoutEditorDialog"
process="#this"
action="#{calendarView.editLockout(row.key.roomNumber,column)}"
oncomplete="lockoutDialogWidget.show()"
rendered="#{row.value[column].text == 'K'}">
<f:attribute name="title" value="#{row.value[column].label}" escape="true" />
</p:commandLink>
</p:columns>
</p:dataTable>
UPDATE:
I've changed p:columns to a simple p:column for testing and it works:
<p:column id="testcolumn">
<p:commandLink id="lockouttest"
value="T"
update=":mainForm:lockoutEditorDialog"
process="#this"
action="#{calendarView.editLockout(15,15)}"
oncomplete="lockoutDialogWidget.show()"
>
</p:commandLink>
</p:column>
Use actionListener instead of action when you want to call a method in your backing bean.
Also, make sure your p:commandLink is placed within a h:form (I assume you've ommited it here since it should be a parent of your p:datatable)

Binding in JSF not working

I am trying to make a h:panelgrid visible and invisible by clicking on a button that's why i made this code:
<p:menu styleClass="ui-menubar" style="width:auto">
<p:menuitem value="khraaaaaaaaa" actionListener="#{accounts.buttonUser()}"></p:menuitem>
</p:menu>
<h:panelGrid id="naalobouk" binding="#{accounts.pg1}">
<h1>Activer/désactiver un compte étudiant</h1>
<hr/>
<h:form id="etudiants">
<p:dataTable emptyMessage="Pas d'étudiant!"
paginator="true"
paginatorPosition="bottom"
rows="4"
value="#{accounts.etudiants}"
var="stu">
<f:facet name="header">
<h:outputText value="Les comptes étudiant" />
</f:facet>
<p:column headerText="#">
<h:outputText value="#{stu.id}" />
</p:column>
<p:column headerText="nom">
<h:outputText value="#{stu.nom}" />
</p:column>
<p:column headerText="prenom">
<h:outputText value="#{stu.prenom}" />
</p:column>
<p:column headerText="email">
<h:outputText value="#{stu.email}" />
</p:column>
<p:column headerText="password">
<h:outputText value="#{stu.password}" />
</p:column>
<p:column headerText="action">
<p:commandButton rendered="#{accounts.butshow}" value="#{stu.actif?'desactiver':'activer'}" action="#{accounts.doToggleStudentState(stu)}" update=":etudiants"/>
</p:column>
</p:dataTable>
</h:form>
</h:panelGrid>
and here is my bean code
private HtmlPanelGrid pg1 = new HtmlPanelGrid();//getter and setter
public void buttonUser(){
if(pg1.isRendered()==true){
pg1.setRendered(false);;
}
if(pg1.isRendered()==false){
pg1.setRendered(true);
}
}
When i click on the button nothing happens. What's the problem here ?
I'm assuming you want the method to negate the rendered property. In that case the method is flawed, as mentioned in the comments. The simplest code would be
public void buttonUser() {
pg1.setRendered(!pg1.isRendered());
}
The main problem is that the p:menuItem by default uses ajax, which by default does'nt update anything on the page. So either update something, or don't use ajax;
<p:menuitem value="khraaaaaaaaa" actionListener="#{accounts.buttonUser()}" ajax="false">
With ajax you need to wrap the panelGrid in a component that will always be rendered, since you can't update a component that has not been rendered in the first place. Wrap the panelGrid in a panelGroup:
<h:panelGroup id="container">
and update that:
<p:menuitem value="khraaaaaaaaa" actionListener="#{accounts.buttonUser()}" update=":container">

Can't pass object to managed bean via a p:contextMenu in a p:dataTable

I have a problem with Primefaces data-table and context menu.
Context menu contains only one option, which deletes row with records.
How I understood, I need to pass to managed bean var parameter (order)? which contains row data in map structure.
<p:dataTable id="#{id}" var="order" rowIndexVar="rowId" value="#{ordersProvider}" emptyMessage="No more rows" rowKey="#{id}" selectionMode="single">
<p:column headerText="№" filterBy="#{order.id}" filterMatchMode="contains">
<div style="text-align: center;">
<h:outputText value="#{order.id}"/>
</div>
</p:column>
<p:column headerText="№ on site" filterBy="#{order.noticeNumber}" filterMatchMode="contains">
<div style="text-align: center;">
<h:outputText value="#{order.noticeNumber}" />
<f:param name="searchString" value="#{order.noticeNumber}" />
</div>
</p:column>
<p:column headerText="Company" filterBy="#{order.customerName}" filterMatchMode="contains">
<div style="text-align: center;">
<h:outputText value="#{order.customerName}"/>
</div>
</p:column>
<p:column id="col">
<f:facet name="header">
<p:contextMenu for="#{id}">
<p:menuitem value="Delete" update="#{id}" icon="ui-icon-close" action="#{clientOrdersBean.cancel(order)}"/>
</p:contextMenu>
</f:facet>
</p:column>
</p:dataTable>
Here is my bean method, for deleting data.
public void cancel(OrderBG order){
order.setStatus(OrderStatus.Canceled);
Environment.getInstance().getServiceProvider().getOrderBgService().save(order);
}
The problem is, that value passes - null. I don't know how to get whole row from table.
Any suggestions? Thank you in advance.
Problem was successfully resolved by getters and setters.
In managed bean:
private OrderBG newOrder = new OrderBG();
public OrderBG getNewOrder() {
return newOrder;
}
public void setNewOrder(OrderBG newOrder) {
this.newOrder = newOrder;
}
public void cancel(){
getNewOrder().setStatus(OrderStatus.Canceled);
Environment.getInstance().getServiceProvider().getOrderBgService().save(getNewOrder());
}
In xhtml UI:
<p:contextMenu for="#{id}">
<p:menuitem value="Delete" update="#{id}" icon="ui-icon-close" actionListener="#{clientOrdersBean.cancel}"/>
</p:contextMenu>
<p:dataTable id="#{id}" var="order" value="#{ordersProvider}" emptyMessage="Заявки отсутствуют" rowKey="#{id}" selection="#{clientOrdersBean.newOrder}" selectionMode="single">

p:commandButton not working within a p:dataTable while using filter

I am using JSF, Primefaces 5.2 and GlassFish 4.1.
I have set up a simple project to test and replicate my larger issue and found it is repeatable within the test project.
I have a simple page with a simple list of objects. I am using the <p:dataTable> and using the global search capability and pagination.
Table Code
<ui:define name="content">
<h:form id="carsForm" >
<p:dataTable id="singleDT" var="c" value="#{testFlow.cars}" widgetVar="carsTable" rows="10" paginator="true"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,15" emptyMessage="No cars found with the given criteria" reflow="true"
filteredValue="#{testFlow.filteredCars}">
<f:facet name="header">
<p:outputPanel class="fright">
<h:outputText value="Search all fields: " />
<p:inputText id="globalFilter" onkeyup="PF('carsTable').filter()" style="width:200px" placeholder="Enter keyword" />
</p:outputPanel>
<p:outputPanel class="Fleft">
<p:commandButton value="New Car" action="addCar" />
</p:outputPanel>
<div class="EmptyBox5"></div>
</f:facet>
<p:column filterBy="#{c.id}" headerText="ID" sortBy="#{c.id}" >
<h:outputText value="#{c.id}"/>
</p:column>
<p:column filterBy="#{c.m}" headerText="Model Year" sortBy="#{c.modelYear}" >
<h:outputText value="#{c.modelYear}"/>
</p:column>
<p:column filterBy="#{c.make}" headerText="Make" sortBy="#{c.make}" >
<h:outputText value="#{c.make}"/>
</p:column>
<p:column filterBy="#{c.model}" headerText="Model" sortBy="#{c.model}" >
<h:outputText value="#{c.model}"/>
</p:column>
<p:column filterBy="#{c.color}" headerText="Color" sortBy="#{c.color}" >
<h:outputText value="#{c.color}"/>
</p:column>
<p:column style="width: 200px; text-align: center">
<p:commandButton actionListener="#{testFlow.removeCar(c)}" value="Delete" update="singleDT messages" ajax="true" >
<p:confirm header="Confirmation" message="Are you sure?" icon="ui-icon-alert" />
</p:commandButton>
</p:column>
</p:dataTable>
<div class="EmptyBox5"></div>
<p:panel>
<p:commandButton action="returnFromTestFlow" value="Exit the Flow" />
</p:panel>
</h:form>
<p:messages id="messages" autoUpdate="true" closable="true" />
<p:confirmDialog global="true" showEffect="fade" hideEffect="explode">
<p:commandButton value="Yes" type="button" styleClass="ui-confirmdialog-yes" icon="ui-icon-check" />
<p:commandButton value="No" type="button" styleClass="ui-confirmdialog-no" icon="ui-icon-close" />
</p:confirmDialog>
</ui:define>
My Controller has a simple method to remove the object.
Method
public String removeCar(Inventory c) {
String redirectTo = "/testFlow/testFlow";
try {
this.cars.remove(c);
iFacade.remove(c);
} catch (Exception e) {
System.out.println(e.getMessage());
}
return redirectTo;
}
When I remove all the filtering and sorting, the method is called after I click yes and the row is deleted. While the filtering and sorting is in place, however, the entire table just re displays as empty but no method is ever called. No error appears, and while using the debugger it never hits a break-point within the method in question.
Any help or direction would be greatly appreciated.
I think the problem is that the datatable is first rendered using the list you provided, but when you press a button it searches through the filtered list and since this is empty at first it cannot locate the button. Notice on the other hand, that if you enter a search criteria and delete it again, the buttons work. This is because the filtered list has been populated and the button can now be located. To solve this problem you need to populate the filtered list with all the values pre render. In your case:
In your backing bean:
public void init()
{
if(!FacesContext.getCurrentInstance().isPostback())
{
filteredCars = cars;
}
}
In your xhtml file:
<f:event type="preRenderView" listener="#{testFlow.init}"/>;
Another way is using the #PostConstruct annotation on your init() function instead of <f:event type="preRenderView />which is clearer code, but, in my opinion, a bit vague in terms of when the function is called.
Had the same problem, #djst solution didn't work for me, but I ended up fixing the problem by using Omnifaces form (o:form) instead of standard h:form. Not sure why, though, but may be worth a try.
When you are using the filtering, primefaces creates a list and shows it in the result, when you are deleting an item from the main list, it has nothing to do with the display list, and this may cause problems like what happened to you.

Resources