JSF page doesnot work when i add selectOneMenu (prime faces) - jsf

i have a managed bean called Lecturer. Lecturer managed bean includes a relation between departments. I want to show all departments stored in the database. when i register a lecturer i need to get its department.
My Lecturer managed bean. i have proper setter and getter methods. i just omit it for clarification.
public class Lecturer
{
private String name;
private String surname;
private String email;
private String username;
private String password;
private List<Department> departments;
private LecturerService lecturerService;
private DepartmentService departmentService;
}
my Licturer.xhtml file:
<h:form>
<f:view>
<p:panelGrid columns="2">
<f:facet name="header">Lecturer Registration Form</f:facet>
<h:outputLabel for="name" value="Name :" />
<p:inputText id="name" value="#{Lecturer.name}" label="Name" required="true" />
<h:outputLabel for="surname" value="Surname :" />
<p:inputText id="surname" value="#{Lecturer.surname}" label="Surname" required="true" />
<h:outputLabel for="department" value="Department :" />
<p:selectOneMenu value="#{Lecturer.departments}" effect="fade" editable="true" var="p" >
<f:selectItem itemLabel="Select One" itemValue="" />
<f:selectItems value="#{Lecturer.departments}" var="lec"
itemLabel="#{lec.name}" itemValue="#{lec.name}"/>
</p:selectOneMenu>
<h:outputLabel for="email" value="Email :" />
<p:inputText id="email" value="#{Lecturer.email}" label="Email" required="true" />
<h:outputLabel for="username" value="User Name :" />
<p:inputText id="username" value="#{Lecturer.username}" label="Email" required="true" />
<h:outputLabel for="password" value="Password :" />
<p:inputText id="password" value="#{Lecturer.password}" label="Password" required="true" />
<f:facet name="footer">
<p:commandButton type="submit"
id="lecturer"
action="#{Lecturer.registerLecturer}"
value="Register" icon="ui-icon-disk">
</p:commandButton>
</f:facet>
</p:panelGrid>
</f:view>
</h:form>
my faces-config.xml
<managed-bean>
<managed-bean-name>Lecturer</managed-bean-name>
<managed-bean-class>com.studinfo.controller.Lecturer</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>departmentService</property-name>
<property-class>com.studinfo.services.DepartmentService</property-class>
<value>#{DepartmentService}</value>
</managed-property>
<managed-property>
<property-name>lecturerService</property-name>
<property-class>com.studinfo.services.LecturerService</property-class>
<value>#{LecturerService}</value>
</managed-property>
</managed-bean>
when i remove the selectOneMenu tag. my page works properly.
any idea about the solution?
Do i must add a converter between string and Department class?

The value attribute of p:selectOneMenu should hold the reference to a single department (this is the selected department) and not the whole list. You need to add a field for this in your bean, e.g.:
private Department selectedDepartment
// getter and setter
Then in your facelet change the value attribute of p:selectOneMenu and the f:selectItems:
<p:selectOneMenu value="#{Lecturer.selectedDepartment}" effect="fade"
editable="true" var="p" >
<f:selectItem itemLabel="Select One" itemValue="" />
<f:selectItems value="#{Lecturer.departments}" var="lec"
itemLabel="#{lec.name}" itemValue="#{lec}"/>
</p:selectOneMenu>
Furthermore you will need a converter to map selected strings to objects.

Related

primefaces datatable not working properly

Following XHTML code for primefaces datatable.
<h:panelGroup id="mode">
<p:panelGrid columns="2">
<p:panelGrid columns="2">
<p:outputLabel style="font-weight: bold;"
value="Mode Of Payments" />
<p:selectOneRadio value="#{invoiceBean.modeOfPayment}"
layout="pageDirection">
<f:ajax render="mode" />
<f:selectItem itemLabel="Cash" itemValue="Cash" />
<f:selectItem itemLabel="Cheque" itemValue="Cheque" />
</p:selectOneRadio>
<p:outputLabel value="Enter Bank Name :" />
<p:inputText value="#{invoiceBean.bankName}"
disabled="#{invoiceBean.modeOfPayment == 'Cash'}" />
<p:outputLabel value="Enter Cheque Number :" />
<p:inputText value="#{invoiceBean.chequeNumber}"
disabled="#{invoiceBean.modeOfPayment == 'Cash'}" />
<p:outputLabel value="Enter Amount :" />
<p:inputText value="#{invoiceBean.chequeAmount}" />
</p:panelGrid>
<p:panelGrid columns="1">
<p:dataTable id="transactionTable"
value="#{invoiceBean.transactions}" var="transaction">
<p:column headerText="Mode Of Payment">
<p:outputLabel value="#{transaction.modeOfPayment}" />
</p:column>
<p:column headerText="Bank Name">
<p:outputLabel value="#{transaction.bankName}" />
</p:column>
<p:column headerText="Amount">
<p:outputLabel value="#{transaction.chequeAmount}" />
</p:column>
<p:column headerText="Balance">
<p:outputLabel value="#{transaction.balance}" />
</p:column>
<p:summaryRow>
<p:column colspan="3">
<p:outputLabel value="Remaining Balance" />
</p:column>
<p:column>
<p:outputLabel value="#{transaction.balance}" />
</p:column>
</p:summaryRow>
</p:dataTable>
</p:panelGrid>
</p:panelGrid>
</h:panelGroup>
<p:commandButton value="Save New Invoice"
action="#{invoiceBean.addRow}"
update=":form:invoiceTable :form:transactionTable growl"
process="#form invoiceTable" onclick="PF('addInvoice').hide();">
<f:ajax render=":form:transactionTable" />
<f:ajax render=":form:invoiceTable" />
</p:commandButton>
Following managed beans code for transactionTable :
#PostConstruct
public void init() {
session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true);
transactionDao = new TransactionDao();
invoiceDao = new InvoiceDao();
invoices = invoiceDao.getInvoiceData(invoiceNumber);
transactions = transactionDao.getTransactions(invoices.get(0).getId());
invoiceProductsServicesDetails = invoiceDao
.getInvoiceProductsServicesDetailDatas();
}
When I add new record in HTML table it will display in transactionTable when click on "Save New Invoice".
Its work first time properly but when I click on radio button and select "Cheque" option new data not display and its replace old data.
You're not supposed to perform business logic in getters/setters.
A normal getter/setter pair looks like this (exactly like as the average IDE would autogenerate for you):
public List<Transaction> getTransactions() {
return transactions;
}
public void setTransactions(List<Transaction> transactions) {
this.transactions = transactions;
}
You should never change them unless you really know what you're doing. In your particular case, the <p:dataTable> calls the getter on every iteration round. You're basically calling the DAO for every single row. This doesn't make sense. This has a huge performance impact if there are lots of records.
In order to preload the data for view, one of the ways is a #PostConstruct method (the bean should preferably be #ViewScoped for this kind of view):
#PostConstruct
public void init() {
transactions = transactionDao.getTransactions(invoices.get(0).getId());
}
In order to save/update the data after edit, just use the action(listener) method.
See also:
Why JSF calls getters multiple times

JSF multiple beans in one View, to get list of entities in db

Ok, I've been discusing this with my colleages, and we can't find if what we are doing is ok or not, supose you have this view,
<h:form id="UsuarioEditForm">
<h:panelGroup id="display" styleClass="createPanelGrid">
<p:panelGrid columns="2">
<p:outputLabel value="Nombre de Usuario: " for="nombreUsuario" />
<p:inputText id="nombreUsuario" value="#{usuarioController.selected.nombreUsuario}" required="true" requiredMessage="Nombre requerido."/>
<p:outputLabel value="Contraseña: " for="password" />
<p:password id="password" value="#{usuarioController.selected.password}" required="true" requiredMessage="Contraseña requerida."/>
<p:outputLabel value="Correo Electrónico: " for="email" />
<p:inputText id="email" value="#{usuarioController.selected.email}" required="true" requiredMessage="Correo electrónico requerido."/>
<p:outputLabel value="Tipo de Usuario: " for="tipoUsuario" />
<h:selectOneMenu id="tipoUsuario" value="#{usuarioController.selected.tipoUsuario}" required="true" requiredMessage="Tipo de Usuario requerido." converter="#{tipoUsuarioConverter}">
<f:selectItem itemLabel="Seleccionar..."/>
<f:selectItems value="#{tipoUsuarioController.items}"
var="tipoUsuarioItem" itemValue="#{tipoUsuarioItem}" itemLabel="#{tipoUsuarioItem.tipo}" />
</h:selectOneMenu>
</p:panelGrid>
<p:separator></p:separator>
<p:commandButton styleClass="ui-priority-primary" actionListener="#{usuarioController.save}" value="Guardar" update="display,:UsuarioListForm:datalist,:growl" oncomplete="handleSubmit(xhr,status,args,UsuarioEditDialog);"/>
<p:commandButton value="Cancelar" type="button" onclick="UsuarioEditDialog.hide()"/>
</h:panelGroup>
</h:form>
the main managed bean who control the whole operation is called usuarioController, this bean do the logic to insert a Usuario entity, but, this entity needs a TipoUsuario entity for correct insert, so we have another bean called tipoUsuarioController that get the list of TipoUsuario entity and display it in a selectOneMenu where the user choose one TipoUsuario, so, the question is simple, it's ok to call a bean just to perform the operation to get the TipoUsuario List?, or it's better to get the List inside the usuarioController bean? Which operation is the best for the application performance?.
Thanks,

setting the values of credit/debit textbox in JSF

I have two textbox in jsf
1)creditAmount
2)debit amount
Now if I type in credit textbox, debit textbox should be zero and and viceversa.
How to do it in jsf? I wrote javascript function for it but it's not working. Is there any way to do it in jsf. I am new in jsf?
<p:inputText id="debitAmount" value="#{jvDetailsController.selected.debitAmount}"
title="#{bundle.CreateJvDetailsTitle_debitAmount}" required="true"
requiredMessage="#{bundle.CreateJvDetailsRequiredMessage_debitAmount}">
<f:convertNumber minFractionDigits="2" pattern="#0.000" />
</p:inputText>
You can easily do that with JSF ajax.
<h:inputText id="credit" value="#{bean.credit}">
<f:ajax event="blur" render="devit" listener="#{bean.changeDevit}"/>
</h:inputText>
<h:inputText id="devit" value="#{bean.devit}">
<f:ajax event="blur" render="credit" listener="#{bean.changeCredit}"/>
</h:inputText>
Here is corresponding ManagedBean
#ManagedBean(name="bean")
class Bean{
int devit;
int credit;
public void changeDevit(){
devit=0;
}
public void changeCredit(){
credit=0;
}
//getter & setter
}
You can use primefaces ajax for this like
<h:panelGrid columns="3">
<h:outputText value="Keyup: " />
<p:inputText id="counter">
<p:ajax event="keyup" update="out"
listener="#{counterBean.increment}"/>
</p:inputText>
<h:outputText id="out" value="#{counterBean.count}" />
</h:panelGrid>
Hope it will hep.

How to retrieve values of textboxes in JSF managed bean which are generated through a loop?

I need to generate textboxes through a loop as follows.
<p:panel id="dataPanel" closable="true" toggleOrientation="horizontal" toggleable="true" header="Data">
<h:panelGrid id="dataPanelGrid" columns="3" cellpadding="5">
<c:forEach var="row" items="#{zoneChargeManagedBean.list}">
<p:outputLabel for="txtCharge" value="#{row[1]}"/>
<p:inputText id="txtCharge" value="#{row[2]}" converter="#{bigDecimalConverter}" onkeydown="return isNumberKey(event, this.value);" label="#{row[1]}" required="false" maxlength="45">
<f:validator validatorId="negativeNumberValidator"/>
<f:attribute name="isZeroAllowed" value="false"/>
<f:validator validatorId="bigDecimalRangeValidator"/>
<f:attribute name="minPrecision" value="1"/>
<f:attribute name="maxPrecision" value="33"/>
<f:attribute name="scale" value="2"/>
</p:inputText>
<p:message for="txtCharge" showSummary="false"/>
</c:forEach>
<p:commandButton id="btnSubmit" update="dataPanel messages" actionListener="#{zoneChargeManagedBean.insert}" icon="ui-icon-check" value="Save"/>
<p:commandButton value="Reset" update="dataPanel" process="#this">
<p:resetInput target="dataPanel" />
</p:commandButton>
</h:panelGrid>
</p:panel>
The value of the given textbox is a type of BigDecimal from the database.
When the given command button is pressed, the values held by these textboxes should be retrieved from the corresponding JSF managed bean so that they can either be inserted or updated in the database.
It would be even better, if it is possible to retrieve the values of all of these text fields at once in some kind of collection (like java.util.List), when the given button is pressed.
<ui:repeate>, a render time tag works correctly but not <c:foreEach>, a view build time component (I can't clarify why) but in this particular case, I found <p:dataGrid> is more suitable. The XHTML has been modified accordingly as follows.
<p:panel id="dataPanel" rendered="#{zoneChargeManagedBean.renderedDataPanel}" closable="true" toggleOrientation="horizontal" toggleable="true" header="Data">
<p:dataGrid columns="3" value="#{zoneChargeManagedBean.list}" var="row" paginator="true" paginatorAlwaysVisible="false" pageLinks="10" rows="15">
<p:watermark for="txtCharge" value="Enter charge."/>
<p:tooltip for="lblCharge" value="Some message."/>
<p:column>
<p:outputLabel id="lblCharge" for="txtCharge" value="#{row[1]}"/><br/>
<p:inputText id="txtCharge" value="#{row[2]}" onkeydown="return isNumberKey(event, this.value);" converter="#{bigDecimalConverter}" label="#{row[1]}" required="false" maxlength="45">
<f:validator validatorId="negativeNumberValidator"/>
<f:attribute name="isZeroAllowed" value="false"/>
<f:validator validatorId="bigDecimalRangeValidator"/>
<f:attribute name="minPrecision" value="1"/>
<f:attribute name="maxPrecision" value="33"/>
<f:attribute name="scale" value="2"/>
</p:inputText>
<h:message for="txtCharge" showSummary="false" style="color: #F00;"/>
</p:column>
</p:dataGrid>
<p:commandButton id="btnSubmit" update="dataPanel messages" actionListener="#{zoneChargeManagedBean.insert}" icon="ui-icon-check" value="Save"/>
<p:commandButton value="Reset" update="dataPanel" process="#this">
<p:resetInput target="dataPanel" />
</p:commandButton>
</p:panel>
The managed bean:
#Controller
#Scope("view")
public final class ZoneChargeManagedBean implements Serializable
{
#Autowired
private final transient ZoneChargeService zoneChargeService=null;
private ZoneTable selectedZone; //Getter and setter
private List<Object[]>list; //Getter and setter
private boolean renderedDataPanel; //Getter and setter
public ZoneChargeManagedBean() {}
public void ajaxListener() {
if(this.selectedZone!=null){
list=zoneChargeService.getZoneChargeList(this.selectedZone.getZoneId());
renderedDataPanel=true;
}
else {
renderedDataPanel=false;
}
}
public void insert() {
//Just do whatever is needed based on the list with new values which is retrieved when <p:commandButton> as shown in the given XHTML is clicked.
if(selectedZone!=null&&zoneChargeService.addOrUpdate(list, selectedZone)) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Message Summary", "Message"));
}
else {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_FATAL, "Message Summary", "Message"));
}
}
}
The service method as in the ajaxListener() method returns a list of type of an array of objects - List<Object[]>.
public List<Object[]>getZoneChargeList(Long id) {
return entityManager.createQuery("select w.weightId, w.weight, zc.charge from Weight w left join w.zoneChargeSet zc with zc.zoneTable.zoneId=:id order by w.weight").setParameter("id", id).getResultList();
}
I can't use the corresponding JPA criteria query which is intended because the with operator which doesn't seem to be supported by the JPA criteria API.
This method is invoked when an item from <p:selectOneMenu> is selected which is not covered in this question.

selecting item from primeface's selectOneMenu not working

I'm having problem with getting the selected item from a selectOneMenu.Here is my JSF code:
<h:form id="mainfrm">
<h:panelGrid columns="2" style="margin-bottom:10px" cellpadding="5">
<h:outputText value="Basic Usage: " />
<p:selectOneMenu id="domaine" value="#{projet.currentDomaines}">
<f:selectItem itemLabel="Select One" itemValue="" />
<f:selectItems value="#{projet.initDomaines()}" var="d" itemValue="#{d}" itemLabel="#{d.libelleDomaine}" />
<p:ajax update="formEquipe" process="mainfrm" event="change" />
</p:selectOneMenu>
</h:panelGrid>
</h:form>
<h:form id="formEquipe">
<h:panelGrid id="display" columns="2" cellpadding="4">
<f:facet name="header">
<p:graphicImage value="/images/cars/xxxx.jpg"/>
</f:facet>
<h:outputText value="Domaine name :" />
<h:outputText value="#{projet.currentDomaines.libelleDomaine}"/>
<h:outputText value="Director :" />
<h:outputText value="#{projet.currentDomaines.nomDirecteur}" />
</h:panelGrid>
</h:form>
it seems like everything is right but i must be missing something... so i tested by changing the currentDomaines (object type Domaines) by text (String) and it worked, and here is the code :
<h:form id="mainfrm">
<h:panelGrid columns="2" style="margin-bottom:10px" cellpadding="5">
<h:outputText value="Basic Usage: " />
<p:selectOneMenu id="domaine" value="#{projet.text}">
<f:selectItem itemLabel="Select One" itemValue="" />
<f:selectItems value="#{projet.initDomaines()}" var="d" itemValue="#{d.libelleDomaine}" itemLabel="#{d.libelleDomaine}" />
<p:ajax update="formEquipe" process="mainfrm" event="change" />
</p:selectOneMenu>
</h:panelGrid>
</h:form>
<h:form id="formEquipe">
<h:panelGrid id="display" columns="2" cellpadding="4">
<f:facet name="header">
<p:graphicImage value="/images/cars/xxxx.jpg"/>
</f:facet>
<h:outputText value="Domaine name :" />
<h:outputText value="#{projet.text/>
</h:panelGrid>
</h:form>
and here is my backing bean:
public class ProjetsBean implements Serializable {
private DomainesService domainesService;
private Domaines currentDomaines;
private String text;
/////////////// setters & getters \\\\\\\\\\\\\\\\\\\
public void setCurrentDomaines(Domaines currentDomaines) {
this.currentDomaines=currentDomaines;
}
public Domaines getCurrentDomaines() {
return currentDomaines;
}
public void setText(String text) {
this.text=text;
}
public Integer getText() {
return text;
}
///////////////// Méthodes \\\\\\\\\\\\\\\
#PostConstruct
public List<Domaines> initDomaines() {
return domainesService.getAllDomaines();
}
}
The selection from a html selectbox will always be returned to the server as string. If you want to use objects in h:selectOneMenu you need a converter.
There is a comprehensive tutorial on that topic: "Objects in h:selectOneMenu".
For the most cases you can do it without an converter, but this is not wrong.
Here is an example:
<h:selectOneMenu value="#{bean.selectedObject.id}">
<f:selectItems value="#{bean.listOfObjects}" var="item" itemLabel="#{item.title}" itemValue="#{item.id}" />
</h:selectOneMenu>
Another idea is to use the hashcode instead of the ID (but in both: itemValue and value).

Resources