selected item in selectonemenu is always null - jsf-2

I am trying to use a <p:dataTable> to display the contents of an object selected from a <p:selectOneMenu> list.
The <p:selectOneMenu> is correctly populated with options. However:
The <p:dataTable> is not updated when I select an item from the <p:selectOneMenu>
The server log indicates that the value of #{MB.selectedDatabase} is null.
#{MB.setSelectedDatabase()} is never invoked.
XHTML:
<h:form id="form">
<h:messages id="messages" />
<p:panelGrid columns="2">
<p:outputLabel value="Data:" />
<p:selectOneMenu immediate="true" id="customDatas" value="#{MB.selectedDatabase}" >
<p:ajax execute="customDatas" render="infos" listener="#{MB.whatIsSelected()}" />
<f:selectItem itemLabel="Select Data" itemValue="" />
<f:selectItems value="#{MB.datas}" var="data" itemLabel="#{data.name}" itemValue="#{data.id}"/>
</p:selectOneMenu>
</p:panelGrid>
<p:dataTable value="#{MB.selectedDatabase.infos}" var="item" id="infos" >
<p:column >
<f:facet name="header">
<h:outputText value="Info"/>
</f:facet>
<h:outputText value="#{item.info}"/>
</p:column>
</p:dataTable>
</h:form>
Partial code from my sessionScoped Bean:
public Data selectedDatabase;
public void whatIsSelected(){
logger.log(Level.SEVERE, "Selected data is : {0}", selectedDatabase.getName());
infoBusinessLocal.getinfosbydata(selectedDatabase);
}
public Data getSelectedDatabase() {
return selectedDatabase;
}
public void setSelectedDatabase(Data selectedDatabase) {
logger.log(Level.SEVERE, "Set selectedDB is invoked");
this.selectedDatabase = selectedDatabase;
}

SelectOneMenu with Pojo classes is needed a JSf converter between page and managed bean. Converter converts string from page to objects in managed beans.
#FacesConverter("dataConverter")
public class DataConverter implements Converter {
#Override
public Object getAsObject(FacesContext context, UIComponent component,
String value) {
//return proper object, value is the string on the page
}
#Override
public String getAsString(FacesContext arg0, UIComponent arg1, Object obj) {
//return the string value of object which will be presented on the page
}
}
Add converter attribute to SelectOneMenu
<p:selectOneMenu immediate="true" id="customDatas" value="#{MB.selectedDatabase}" converter="dataConverter">
See also
BalusC SelectOneMenu tutorial

Related

Primefaces autoComplete parameter of getAsString method Object is null inside of my converter

I am migrating from Icefaces selectInputText to Primefaces autoComplete component.
<ice:selectInputText styleClass="adminAppUserSelect"
id="searchUser" value="#{appUserData.selectedUserName }" rows="50"
width="100%" listVar="userList"
valueChangeListener="#{appUserData.updateListUser}"
binding="#{appUserData.userAutoComplete}"
title="#{msg.WEB_ADMIN_PAGES_APPUSER_AUTOCOMPLETE}"
listValue="#{appUserData.matchesListUser}">
<f:facet name="selectInputText" >
<ice:panelGrid columns="3" width="400px" columnClasses="width20,width40,width40">
<ice:outputText
value="#{userList.iappuserId}" />
<ice:outputText
value="#{userList.cappuserName}" />
<ice:outputText
value="#{userList.cappuserDesc}" />
</ice:panelGrid>
</f:facet>
</ice:selectInputText>
I am using Primefaces 5.3.5 with JSF 2.2.8.
I see the same number of autocomplete result as my older version has in Icefaces 1.2 but I do not see user details. I see only number 0 in the first cell of each row.
<p:autoComplete id="searchUser" styleClass="adminAppUserSelect" value="#{appUserData.selectedUserName}"
maxResults="50" var="appUser" completeMethod="#{appUserData.completeUserList}"
binding="#{appUserData.userAutoComplete}" title="#{msg.WEB_ADMIN_PAGES_APPUSER_AUTOCOMPLETE}"
itemValue="#{appUser}" itemLabel="#{appUser.cappuserName}" converter="appUserConverter">
<!--<p:ajax event="itemSelect" listener="#{appUserData.updateListUser}"/>-->
<p:column>
<h:outputText value="#{appUser.iappuserId}" />
</p:column>
<p:column>
<h:outputText value="#{appUser.cappuserName}" />
</p:column>
<p:column>
<h:outputText value="#{appUser.cappuserDesc}" />
</p:column>
</p:autoComplete>
I am not sure about my converter that looks like
#FacesConverter("appUserConverter")
public class AppUserConverter implements Converter {
private int i;
#Override
public Object getAsObject(FacesContext fc, UIComponent uic, String value) {
...
}
#Override
public String getAsString(FacesContext fc, UIComponent uic, Object object) {
if(object == null)
return null;
else{
return ((VAppuser) object).getCappuserName();
}
}
}
my result of autoComplete component
Can you advise me, please what I made wrong?
UPDATED:
I see that value(data-item-value) is set properly but label(data-item-label) is not set yet.
ADDED
I noticed during debugging of my code that items
if(items != null) {
for(Object item : items) {
are correctly assigned to list that got from completeMethod but ac.getItemValue() passes object that has null properties at this line
String value = converter == null ? (String) ac.getItemValue() : converter.getAsString(context, ac, ac.getItemValue());
in the Primefaces AutoCompleteRenderer.
I solved it by removing
<bean id="appUser" class="model.admin.usermgmnt.VAppuser"
scope="session">
</bean>
from my application context as it was not necessary for the autoComplete component.

page can't get value from Bean

I have a table p:dataTable. When I select an item, it's refresh another p:dataTable with associed values.
It's works fine. But when I select an item in the second table, the page (xhtml) don't get the value from the bean.
In debug mode I see that the value is updated on bean, but acessing #{bean.value} is always null.
Where is the codes:
<h:form id="form">
<h:panelGrid columns="2">
<!-- FRIST TABLE -->
<p:dataTable id="alunos" var="aluno" emptyMessage="Nenhum aluno cadastrado" value="#{alunos.usuarios}" selectionMode="single" selection="#{alunos.usuarioSelecionado}" rowKey="#{aluno.id}">
<f:facet name="header">
Alunos
</f:facet>
<p:ajax event="rowSelect" listener="#{alunos.onRowSelect}" update=":form:disci" />
<p:column headerText="Nome" width="60%">
<h:outputText value="#{aluno.nome}" />
</p:column>
<p:column headerText="Curso">
<h:outputText value="Default" />
</p:column>
</p:dataTable>
<!-- FUNCTIONS FOR FRIST TABLE THAT ARE WORKING -->
<p:column rowspan="4">
<p:commandButton value="Adicionar" update="alunos" icon="ui-icon-plus" actionListener="#{alunos.addUser()}"/>
<p:commandButton value="Editar" icon="ui-icon-pencil" actionListener="#{alunos.editarUser()}"/>
<p:commandButton value="Remover" icon="ui-icon-close" actionListener="#{alunos.apagaUser()}"/>
</p:column>
</h:panelGrid>
<p:outputLabel for="disci" value="Disciplinas que o aluno cursa" />
<!-- SECOND TABLE - Updated when an iten is selected in frist table (working)-->
<p:dataTable id="disci" var="disciplina" emptyMessage="Selecione um aluno" value="#{alunos.disciplinas}" selectionMode="single" selection="#{alunos.disciplinaSelecionada}" rowKey="#{disciplina.id}">
<p:ajax event="rowSelect" listener="#{alunos.onRowSelectDisciplina}" oncomplete="PF('dDialog').show()"/>
<p:column headerText="Nome" width="80%">
<h:outputText value="#{disciplina.nome}" />
</p:column>
</p:dataTable>
<!-- Dialog to show informations - ALWAYS NULL -->
<p:dialog header="Info" widgetVar="dDialog" modal="true" showEffect="fade" hideEffect="fade" resizable="false">
<p:outputPanel id="detail" style="text-align:center;">
<p:panelGrid columns="2" columnClasses="label,value">
<h:outputText value="Id:" />
<h:outputText value="#{alunos.disciplinaSelecionada.id}" />
<h:outputText value="Nome" />
<h:outputText value="#{alunos.disciplinaSelecionada.nome}" />
</p:panelGrid>
</p:outputPanel>
</p:dialog>
</h:form>
And the Bean:
#ManagedBean(name = "alunos")
#ViewScoped
public class Alunos extends NovoUsuario {
private Disciplina disciplinaSelecionada;
public Alunos() {
super(TiposUsuario.ALUNO);
}
//Method called when an iten is selected in SECOND TABLE
//In debug, the Object Disciplina is correct, as selected in table.
public void onRowSelectDisciplina(SelectEvent event) {
this.disciplinaSelecionada = (Disciplina) event.getObject();
}
//getters and setters
}
extended class:
public class NovoUsuario implements Serializable{
private List<Usuario> usuarios;
protected Usuario usuarioSelecionado;
TiposUsuario tipo;
private String nome;
private String senha;
protected List<Disciplina> disciplinas;
//Constructor
public NovoUsuario(TiposUsuario tipo) {
this.tipo = tipo;
}
//Initialize FRIST TABLE
#PostConstruct
public void init() {
UsuarioCRUD usuarioCRUD = new UsuarioCRUD();
this.usuarios = usuarioCRUD.listarTipoUsuario(tipo);
}
//Method used in FRIST TABLE
public void onRowSelect(SelectEvent event) {
disciplinas = getDisciplinaUsuario();
}
//Method that get data to SECOND table when a row is selectd in frist
public List<Disciplina> getDisciplinaUsuario() {
DisciplinaCRUD dcrud = new DisciplinaCRUD();
if (usuarioSelecionado != null) {
return dcrud.listaDisciplinasUsuario(usuarioSelecionado);
}
return null;
}
public void salvaUsuario() {
/* code to create*/
}
public void editarUser(){
/* code to update*/
}
public void apagaUser(){
/* code to delete*/
}
//GETTERS AND SETTERS
}
image: http://i.stack.imgur.com/Qbs0T.png
repository: https://bitbucket.org/VagnerGon/novo-academico
I'd say you just need to update the dialogs content from the p:ajax in the second table - just as you update the second datatable, when you select in the first.
So add id="dialog" to the dialog, and make the p:ajax in the second table
<p:ajax event="rowSelect" listener="#{alunos.onRowSelectDisciplina}" update=":form:dialog" oncomplete="PF('dDialog').show()" />
Or omit the new id and just do update=":form:detail".

Primefaces datatable hasn't been refreshed after applying the filter

I have some code is similar to the following showcase:
http://www.primefaces.org/showcase/ui/data/datatable/filter.xhtml
The filter is applied correctly in the backing bean, although the datatable hasn't been refreshed with the new filtered rows. It remains as it is before applying the filter. Is there something missing or wrong in this showcase?
<h:form>
<p:dataTable var="serviceEntity" value="#{serviceSearchMB.allServices}" widgetVar="serviceSearchTable"
emptyMessage="No services found with given criteria" filteredValue="#{serviceSearchMB.filteredServices}">
<f:facet name="header">
<h:outputText value="Search all fields:" />
<p:inputText id="globalFilter" onkeyup="PF('serviceSearchTable').filter();"
style="width:150px" placeholder="Enter keyword" />
</f:facet>
<p:column filterBy="#{serviceEntity.serviceName}" headerText="Service Name" filterMatchMode="contains" >
<h:outputText value="#{serviceEntity.serviceName}" />
</p:column>
...
Backing Bean:
#ManagedBean(name="serviceSearchMB")
#RequestScoped
public class ServiceSearchManagedBean implements Serializable {
private List<ServiceSearchEntity> filteredServices;
public List<ServiceSearchEntity> getFilteredServices() {
return filteredServices;
}
public void setFilteredServices(List<ServiceSearchEntity> filteredServices) {
this.filteredServices = filteredServices; // Already set the filtered list correctly.
}
public List<ServiceSearchEntity> getAllServices() {
//already returns all services.
}
...

Save and update on same xhtml is not working in primefaces

Hi i tried the following functionality using primefaces.
In my xhtml i have a input field which takes input and saves into db.After completion of save i display the saved data in data table of primefaces.
Upto now works fine.now i add single selection to datatable .when user click on the row i update the same input column with selected data.
For this i use the following code
<h:form id="form">
<p:growl id="messages" />
<p:panel id="panel" header="Currency">
<h:panelGrid columns="2" id="currencyGrid">
<p:outputLabel value="Currency :"/>
<p:inputText value="#{currencyBean.currencyMaster.currDesc}"/>
</h:panelGrid>
<p:commandButton value="Add" action="#{currencyBean.saveCurrency}"
update="currencytable">
</p:commandButton>
<p:dataTable id="currencytable" var="cur"
value="#{currencyBean.currencyList}" widgetVar="dlg"
selection="#{currencyBean.currencyMaster}"
selectionMode="single" rowKey="#{cur.currId}">
<p:ajax event="rowSelect" listener="#{currencyBean.onRowSelect}"
update=":form:currencyGrid" />
<p:column headerText="ID" style="font-size:12px;">
<h:outputText value="#{cur.currId}" />
</p:column>
<p:column headerText="Description" style="font-size:12px;">
<h:outputText value="#{cur.currDesc}" />
</p:column>
</p:dataTable>
</h:form>
And My Bean code is:
#managedBean
#viewScoped
#component
public class CurrencyBean implements Serializable{
private static final long serialVersionUID = 1L;
#Autowired
private CurrencyMaster currencyMaster;
private List<CurrencyMaster> currencyList;
public CurrencyMaster getCurrencyMaster() {
return currencyMaster;
}
public void setCurrencyMaster(CurrencyMaster currencyMaster) {
this.currencyMaster = currencyMaster;
}
public void saveCurrency(){
try{
currencyService.saveCurrency(currencyMaster);
}catch(Exception e){
e.printStackTrace();
}
}
#PostConstruct
public void currencyList(){
setCurrencyList(currencyService.getCurrencyList());
}
public void onRowSelect(SelectEvent event) {}
public void onRowUnselect(UnselectEvent event) {}
}
So when i click on currrencytable row the input field populated properly and update operation also.
The problem is when i directly enter the data into input column my globalMaster property is going to be null.
And the following error is occured;
attempt to create saveOrUpdate event with null entity
I change the scopes of the bean but i did not find the solution.
And i find more solutions for the above exception but my problem is the new values are does not set to currencymaster.
Is there any mistake i done in this context.please guide me..

Primefaces Dataexporter and get method

With a simple class wich contains only a list of list of String, I can view all its elements in a p:dataTable with the get(int) method of class List but it fails when I try to export this with the p:dataExporter component.
Here's the Java source code :
#ManagedBean
#SessionScoped
public class MainClass {
private List<ArrayList<String>> listOfListOfString;
public List<ArrayList<String>> getListOfListOfString() {
return listOfListOfString;
}
public void setListOfListOfString(List<ArrayList<String>> listOfListOfString) {
this.listOfListOfString = listOfListOfString;
}
public MainClass() {
listOfListOfString = new ArrayList<ArrayList<String>>();
ArrayList<String> firstList = new ArrayList<String>();
firstList.add("a");
firstList.add("b");
listOfListOfString.add(firstList);
ArrayList<String> secondList = new ArrayList<String>();
secondList.add("1");
secondList.add("2");
listOfListOfString.add(secondList);
}
}
And the XTHML code :
<h:body>
Hello from Facelets
<h:form prependId="false">
<p:dataTable id="tbl" var="myList" value="#{mainClass.listOfListOfString}" paginator="true" rows="10" >
<p:column headerText="First column">
<h:outputText value="#{myList.get(0)}"/>
</p:column>
<p:column headerText="Second column">
<h:outputText value="#{myList.get(1)}"/>
</p:column>
</p:dataTable>
<h:commandLink value=" csv">
<p:dataExporter type="csv" target="tbl" fileName="userList" />
</h:commandLink>
</h:form>
</h:body>
And the error stack when I click on the csv link:
For input string: "get"
- Stack Trace
java.lang.NumberFormatException: For input string: "get"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
at java.lang.Integer.parseInt(Integer.java:449)
at java.lang.Integer.parseInt(Integer.java:499)
at javax.el.ListELResolver.coerce(ListELResolver.java:173)
at javax.el.ListELResolver.getType(ListELResolver.java:72)
Do you have an idea why p:dataTable can use the get(int) method and p:dataExporter can't?
Thanks,
Philippe
Probably both components are implemented differently.
But you can access list elements this way:
#{myList[n]}
where n is the list index.

Resources