I have two dropdowns: One is implemented using a selectOneMenu component and the other is implemented with selectCheckboxMenu.
When selecting an option in the selectOneMenu, the option values of the selectCheckboxMenu are updated depending of what option was selected in the selectOneMenu.
The following scenario happens:
I select an option of the selectOneMenu, the selectCheckboxMenu gets populated
I select/check some options of the selectCheckboxMenu
I select another option of the selectOneMenu, the selectCheckboxMenu gets populated with other values
I select some of the new values
I select the option in step 1 of the selectOneMenu
The values I selected in step 2 are no longer selected
I believe this is because the list value bound to the selectCheckboxMenu is getting reset by the setter method.
What I would like is for the state of the selectCheckboxMenu to be globally saved. What would be the best strategy for doing this?
EDIT:
Here's the relevant code that duplicates the previous behavior:
Bean:
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.List;
#ManagedBean
#ViewScoped
public class BackingBean {
private List<Parent> parents = new ArrayList<>();
private List<Child> children = new ArrayList<>();
private List<Child> selectedChildren = new ArrayList<>();
private Parent selectedParent = new Parent();
#Inject
FamilyService service;
#PostConstruct
public void init(){
parents = service.findParents();
}
public void parentChanged(){
children = new ArrayList<>();
if(getSelectedParent() == null){
return;
}
children = service.findChildrenByParent(getSelectedParent());
}
public void selectedSonChanged(){
System.out.println(selectedChildren.size());
}
public List<Parent> getParents() {
return parents;
}
public void setParents(List<Parent> parents) {
this.parents = parents;
}
public List<Child> getChildren() {
return children;
}
public void setChildren(List<Child> children) {
this.children = children;
}
public List<Child> getSelectedChildren() {
return selectedChildren;
}
public void setSelectedChildren(List<Child> selectedChildren) {
this.selectedChildren = selectedChildren;
}
public Parent getSelectedParent() {
return selectedParent;
}
public void setSelectedParent(Parent selectedParent) {
this.selectedParent = selectedParent;
}
}
XHTML:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
<h:body>
<h:form id="selectOne">
<p:messages autoUpdate="true" />
<h:outputLabel for="parents" value="Parents:" />
<p:selectOneMenu converter="#{parentConverter}" id="parents" value="#{backingBean.selectedParent}">
<p:ajax update="children" listener="#{backingBean.parentChanged}" />
<f:selectItem noSelectionOption="true" value="#{null}" itemLabel="None" />
<f:selectItems value="#{backingBean.parents}" var="p" itemLabel="#{p.name}" itemValue="#{p}" />
</p:selectOneMenu>
<h:outputLabel for="children" value="Children:" />
<p:selectCheckboxMenu converter="#{childConverter}" id="children"
value="#{backingBean.selectedChildren}"
label="Children" filter="true" filterMatchMode="startsWith">
<p:ajax update="display" listener="#{backingBean.selectedSonChanged}" />
<f:selectItems value="#{backingBean.children}" var="c" itemLabel="#{c.name}" itemValue="#{c}" />
</p:selectCheckboxMenu>
<p:outputPanel id="display">
<p:dataList value="#{backingBean.selectedChildren}" var="sn" emptyMessage="No children selected">
#{sn.name}
</p:dataList>
</p:outputPanel>
<p:commandButton value="Submit" update="display, selectOne" />
</h:form>
</h:body>
</html>
The complete project is here: https://github.com/cenobyte321/jsfsamples/tree/master/selectcheckboxmenu
You can find a video of the interaction mentioned previously here:
https://github.com/cenobyte321/jsfsamples/blob/master/selectcheckboxmenu/example1.mp4?raw=true
As you can see when choosing another "Parent" and then selecting their children the previous children list gets substituted. How can I properly modify this behavior so the previously selected elements get persisted and shown as checked in the selectCheckboxMenu?
EDIT 2:
One solution I found was introducing another variable which will hold the global values and will be modified in the listener method "selectedSonChanged". Here's the relevant code:
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
#ManagedBean
#ViewScoped
public class BackingBean {
private List<Parent> parents = new ArrayList<>();
private List<Child> children = new ArrayList<>();
private List<Child> selectedChildren = new ArrayList<>();
private List<Child> globalSelectedChildren = new ArrayList<>();
private Parent selectedParent = new Parent();
#Inject
FamilyService service;
#PostConstruct
public void init(){
parents = service.findParents();
}
public void parentChanged(){
children = new ArrayList<>();
if(getSelectedParent() == null){
return;
}
children = service.findChildrenByParent(getSelectedParent());
selectedChildren = globalSelectedChildren.stream().filter(c -> c.getParent().equals(selectedParent)).collect(Collectors.toList());
System.out.println(selectedChildren.size());
}
public void selectedSonChanged(){
System.out.println(selectedChildren.size());
globalSelectedChildren = globalSelectedChildren.stream().filter(c -> !c.getParent().equals(selectedParent)).collect(Collectors.toList());
globalSelectedChildren.addAll(selectedChildren);
}
public List<Parent> getParents() {
return parents;
}
public void setParents(List<Parent> parents) {
this.parents = parents;
}
public List<Child> getChildren() {
return children;
}
public void setChildren(List<Child> children) {
this.children = children;
}
public List<Child> getSelectedChildren() {
return selectedChildren;
}
public void setSelectedChildren(List<Child> selectedChildren) {
this.selectedChildren = selectedChildren;
}
public Parent getSelectedParent() {
return selectedParent;
}
public void setSelectedParent(Parent selectedParent) {
this.selectedParent = selectedParent;
}
public List<Child> getGlobalSelectedChildren() {
return globalSelectedChildren;
}
public void setGlobalSelectedChildren(List<Child> globalSelectedChildren) {
this.globalSelectedChildren = globalSelectedChildren;
}
}
XHTML:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
<h:body>
<h:form id="selectOne">
<p:messages autoUpdate="true" />
<h:outputLabel for="parents" value="Parents:" />
<p:selectOneMenu converter="#{parentConverter}" id="parents" value="#{backingBean.selectedParent}">
<p:ajax update="children" listener="#{backingBean.parentChanged}" />
<f:selectItem noSelectionOption="true" value="#{null}" itemLabel="None" />
<f:selectItems value="#{backingBean.parents}" var="p" itemLabel="#{p.name}" itemValue="#{p}" />
</p:selectOneMenu>
<h:outputLabel for="children" value="Children:" />
<p:selectCheckboxMenu converter="#{childConverter}" id="children"
value="#{backingBean.selectedChildren}"
label="Children" filter="true" filterMatchMode="startsWith">
<p:ajax update="display" listener="#{backingBean.selectedSonChanged}" />
<f:selectItems value="#{backingBean.children}" var="c" itemLabel="#{c.name}" itemValue="#{c}" />
</p:selectCheckboxMenu>
<p:outputPanel id="display">
<p:dataList value="#{backingBean.globalSelectedChildren}" var="sn" emptyMessage="No children selected">
#{sn.name}
</p:dataList>
</p:outputPanel>
<p:commandButton value="Submit" update="display, selectOne" />
</h:form>
</h:body>
</html>
Here's the branch with this solution: https://github.com/cenobyte321/jsfsamples/tree/solution-1/selectcheckboxmenu
Related
What I doing is just an application where the selected option display in the textArea. But Ajax is not working after lending the page after navigation from the main menu on this page. That function only works after using the submit button.
Below is my JSF page code
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
template="/WEB-INF/template.xhtml">
<ui:define name="title">
Ajax Framework - <span class="subitem">Basic</span>
</ui:define>
<ui:define name="description">
This example demonstrates a simple but common usage of posting the form, updating the backend value and displaying the output with ajax.
</ui:define>
<ui:define name="implementation">
<h:form>
<p:panel id="panel" header="Form" style="margin-bottom:10px;">
<p:messages>
<p:autoUpdate />
</p:messages>
<h:panelGrid columns="2" style="margin-bottom:10px" cellpadding="5">
<p:outputLabel for="lazy" value="Lazy:" />
<p:selectOneMenu id="lazy" value="#{selectOneMenuView.option}" lazy="true" style="width:125px">
<f:selectItem itemLabel="Select One" itemValue="" />
<f:selectItems value="#{selectOneMenuView.options}" />
<f:ajax event="change" listener="#{selectOneMenuView.onChange}" execute="#this" render="textarea1"/>
</p:selectOneMenu>
</h:panelGrid>
<p:commandButton value="Submit" update="display" oncomplete="PF('dlg').show()" icon="ui-icon-check" />
<p:dialog header="Values" modal="true" showEffect="bounce" widgetVar="dlg" resizable="false">
<p:panelGrid columns="2" id="display" columnClasses="label,value">
<h:outputText value="Lazy:" />
<h:outputText value="#{selectOneMenuView.option}" />
</p:panelGrid>
</p:dialog>
<h3>AutoResize</h3>
<p:inputTextarea id="textarea1" value="#{selectOneMenuView.inputTextArea}" rows="6" cols="33" />
</p:panel>
</h:form>
</ui:define>
</ui:composition>
And my managed bean is as below
package org.primefaces.showcase.view.input;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.model.SelectItem;
import javax.faces.model.SelectItemGroup;
import org.primefaces.showcase.domain.Theme;
import org.primefaces.showcase.service.ThemeService;
#ManagedBean
public class SelectOneMenuView {
private String console;
private String car;
private List<SelectItem> cars;
private String city;
private Map<String,String> cities = new HashMap<String, String>();
private Theme theme;
private List<Theme> themes;
private String option;
private List<String> options;
private String inputTextArea;
public String getInputTextArea() {
return inputTextArea;
}
public void setInputTextArea(String inputTextArea) {
this.inputTextArea = inputTextArea;
}
#ManagedProperty("#{themeService}")
private ThemeService service;
#PostConstruct
public void init() {
//cars
SelectItemGroup g1 = new SelectItemGroup("German Cars");
g1.setSelectItems(new SelectItem[] {new SelectItem("BMW", "BMW"), new SelectItem("Mercedes", "Mercedes"), new SelectItem("Volkswagen", "Volkswagen")});
SelectItemGroup g2 = new SelectItemGroup("American Cars");
g2.setSelectItems(new SelectItem[] {new SelectItem("Chrysler", "Chrysler"), new SelectItem("GM", "GM"), new SelectItem("Ford", "Ford")});
cars = new ArrayList<SelectItem>();
cars.add(g1);
cars.add(g2);
//cities
cities = new HashMap<String, String>();
cities.put("New York", "New York");
cities.put("London","London");
cities.put("Paris","Paris");
cities.put("Barcelona","Barcelona");
cities.put("Istanbul","Istanbul");
cities.put("Berlin","Berlin");
//themes
themes = service.getThemes();
//options
options = new ArrayList<String>();
for(int i = 0; i < 20; i++) {
options.add("Option " + i);
}
}
public String getConsole() {
return console;
}
public void setConsole(String console) {
this.console = console;
}
public String getCar() {
return car;
}
public void setCar(String car) {
this.car = car;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public Theme getTheme() {
return theme;
}
public void setTheme(Theme theme) {
this.theme = theme;
}
public List<SelectItem> getCars() {
return cars;
}
public Map<String, String> getCities() {
return cities;
}
public List<Theme> getThemes() {
return themes;
}
public void setService(ThemeService service) {
this.service = service;
}
public String getOption() {
return option;
}
public void setOption(String option) {
this.option = option;
}
public List<String> getOptions() {
return options;
}
public void setOptions(List<String> options) {
this.options = options;
}
public void onChange(){
this.inputTextArea = this.option;
}
}
May I know why? Can anyone give me some guideline?
I have this example code,
My xhtml page.
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
</h:head>
<h:body>
<p:dataList value="#{dataListView.lista}" var="l" type="unordered"
itemType="none" paginator="true" rows="1" styleClass="paginated">
<f:facet name="header">
Paginator
</f:facet>
<p:selectOneRadio id="resposta" value="#{dataListView.resposta}">
<f:selectItem itemLabel="Certo" itemValue="Certo" />
<f:selectItem itemLabel="Errado" itemValue="Errado" />
</p:selectOneRadio>
</p:dataList>
</h:body>
</html>
My Bean
package br.com.so.teste;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import br.com.so.modelo.Questao;
#Named
#ViewScoped
public class DataListView implements Serializable {
private List<String> lista;
private String resposta;
#PostConstruct
public void init() {
lista = new ArrayList<>();
lista.add("1");
lista.add("2");
lista.add("3");
lista.add("4");
lista.add("5");
}
public List<String> getLista() {
return lista;
}
public void setLista(List<String> lista) {
this.lista = lista;
}
public String getResposta() {
return resposta;
}
public void setResposta(String resposta) {
this.resposta = resposta;
}
}
The error appear when i change the page view, in pagination have (1,2,3...) if i check the radio button in page '1' and i go to page '2' and i come back to page '1' the radio button is not checked.
Why does it happen?
How do i fix it?
I need to keep the value checked in the radioButtons.
I resolved using this.
I create 2 SelectoneRadio, one geting the checked value, if exists..
And another only puting the value.
I use Ajax to pass the ID.
If the map contains the id, i use ajax only to update, because the radio set the value directly in the map.
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
</h:head>
<h:body>
<h:form id="formulario">
<p:dataList value="#{dataListView.lista}" var="l" type="unordered"
itemType="none" paginator="true" rows="1" styleClass="paginated">
<f:facet name="header">
Paginator
</f:facet>
<p:selectOneRadio value="#{dataListView.teste}"
rendered="#{dataListView.resposta[l] == null}">
<p:ajax listener="#{dataListView.processaResposta(l)}" event="click"
update="formulario"></p:ajax>
<f:selectItem itemLabel="Certo" itemValue="Certo" />
<f:selectItem itemLabel="Errado" itemValue="Errado" />
</p:selectOneRadio>
<p:selectOneRadio value="#{dataListView.resposta[l]}"
rendered="#{dataListView.resposta[l] != null}">
<p:ajax event="click" update="formulario"></p:ajax>
<f:selectItem itemLabel="Certo" itemValue="Certo" />
<f:selectItem itemLabel="Errado" itemValue="Errado" />
</p:selectOneRadio>
</p:dataList>
</h:form>
</h:body>
</html>
And in bean...
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean
#SessionScoped
public class DataListView implements Serializable {
private List<String> lista;
private Map<String, String> resposta;
private String teste;
#PostConstruct
public void init() {
lista = new ArrayList<>();
lista.add("1");
lista.add("2");
lista.add("3");
lista.add("4");
lista.add("5");
resposta = new HashMap<>();
}
public List<String> getLista() {
return lista;
}
public void setLista(List<String> lista) {
this.lista = lista;
}
public Map<String, String> getResposta() {
return resposta;
}
public void setResposta(Map<String, String> resposta) {
this.resposta = resposta;
}
public void processaResposta(String action) {
resposta.put(action, teste);
teste = null;
}
public String getTeste() {
return teste;
}
public void setTeste(String teste) {
this.teste = teste;
}
}
After put a answer and ID, you need to make the value 'teste' null.
I am basing my example on the PrimeFaces showcase example for the p:dataTableContextMenu example
The difference being I am trying to delete via a p:confirmDialog but the selected item is always null.
Here's a cut down example
The XHTML
<!DOCTYPE html>
<html xmlns="http://www.w3c.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>Example</title>s
</h:head>
<h:body>
<h:form>
<p:confirmDialog widgetVar="cd" severity="alert" header="Confirmation"
message="Are you sure you wish to delete this car?">
<p:commandButton value="Yes" action="#{carTableView.deleteCar}"
update=":dataForm" oncomplete="PF('cd').hide();" />
<p:commandButton value="No" onclick="PF('cd').hide();" type="button" />
</p:confirmDialog>
</h:form>
<h:form id="dataForm">
<p:contextMenu for="cars">
<p:menuitem value="Delete" icon="ui-icon-close"
onclick="PF('cd').show(); return false;" />
<!-- action="#{formsView.deleteForm}" update=":dataForm" /> -->
</p:contextMenu>
<p:dataTable id="cars" var="car" value="#{carTableView.cars}"
rowKey="#{car.id}" selection="#{carTableView.selectedCar}"
selectionMode="single">
<f:facet name="header">
RightClick to View Options
</f:facet>
<p:column headerText="Id">
<h:outputText value="#{car.id}" />
</p:column>
<p:column headerText="Name">
<h:outputText value="#{car.name}" />
</p:column>
</p:dataTable>
</h:form>
</h:body>
</html>
The Model
public class Car
{
private String id;
private String name;
public Car(String id, String name)
{
this.id = id;
this.name = name;
}
public String getId()
{
return id;
}
public void setId(String id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
}
And the bean
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#SuppressWarnings("serial")
#ManagedBean
#ViewScoped
public class CarTableView implements Serializable
{
private List<Car> cars;
private Car selectedCar;
#PostConstruct
public void init()
{
cars = createCars();
}
private List<Car> createCars()
{
List<Car> list = new ArrayList<Car>();
for (int i = 0; i < 10; i++)
{
list.add(new Car(UUID.randomUUID().toString().substring(0, 8), "Car " + String.valueOf(i + 1)));
}
return list;
}
public void deleteCar()
{
cars.remove(selectedCar);
selectedCar = null;
}
public List<Car> getCars()
{
return cars;
}
public void setCars(List<Car> cars)
{
this.cars = cars;
}
public Car getSelectedCar()
{
return selectedCar;
}
public void setSelectedCar(Car selectedCar)
{
this.selectedCar = selectedCar;
}
}
Now it seems to me that it's the involvement of running the deleteCar action from the p:confirmDialog that is the issue.
I say this as if I change
<p:menuitem value="Delete" icon="ui-icon-close"
onclick="PF('cd').show(); return false;" />
To
<p:menuitem value="Delete" icon="ui-icon-close"
action="#{formsView.deleteForm}" update=":dataForm" />
Then it works. In the p:confirmDialog example the selectedCar in the deleteCar method is always null. Despite specifying a rowKey attribute in p:dataTable
Since you have two forms, enclose <h:setPropertyActionListener > to your <p:menuitem>
Answer: The p:confirmDialog needs to be part of the same h:form as the p:dataTable
i'm using jsf/primefaces. I want to enable the 'addState' selectOneMenu dropdown should the user select 'Australia' from the 'addCountry' selectOneMenu, it works but on the first instance you have to change the country a couple of times before it will enable, after that it enables/disables on every change. How to get it to respond after first change?
<h:outputLabel value="#{bundle.AddressLabel_country}" for="addcountry" />
<p:selectOneMenu id="addcountry" value="#{addressBean.address.country}" immediate="true" >
<f:selectItems value="#{localeList.getCountryList()}" />
<f:ajax render="addstate"/>
</p:selectOneMenu>
<h:outputLabel value="#{bundle.AddressLabel_state}" for="addstate"/>
<p:selectOneMenu id="addstate" value="#{addressBean.address.state}" disabled="#{addressBean.address.country ne 'Australia'}">
<f:selectItem itemLabel="Select State" itemValue="" />
<f:selectItems value="#{localeList.getAUState()}" />
</p:selectOneMenu>
how about this way
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class AddressBean implements Serializable{
/**
*
*/
private static final long serialVersionUID = 2439322307625952605L;
private List<String> countries;
private List<String> states;
private Address address;
private boolean disableState;
private Map<String,List<String>> map = new HashMap<String,List<String>>();
#PostConstruct
public void init(){
address= new Address();
countries = new ArrayList<String>();
states = new ArrayList<String>();
countries.add("Australia");
countries.add("Other");
String[] s1 = {"state 1","state 2"};
String[] s2 = {"state 3","state 4"};
map.put("Australia", Arrays.asList(s1));
map.put("Other", Arrays.asList(s2));
this.disableState = "Australia".equals(countries.get(0));
}
public void updateState(){
this.states = map.get(this.address.getCountry());
this.disableState = "Australia".equals(this.address.getCountry());
}
public List<String> getCountries() {
return countries;
}
public void setCountries(List<String> countries) {
this.countries = countries;
}
public List<String> getStates() {
return states;
}
public void setStates(List<String> states) {
this.states = states;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public boolean isDisableState() {
return disableState;
}
public void setDisableState(boolean disableState) {
this.disableState = disableState;
}
}
and
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
<h:body>
<h:form>
<h:outputLabel value="Country"
for="addcountry" />
<p:selectOneMenu id="addcountry" value="#{addressBean.address.country}">
<f:selectItems value="#{addressBean.getCountries()}" />
<p:ajax listener="#{addressBean.updateState}" update="addstate"/>
</p:selectOneMenu>
<h:outputLabel value="State" for="addstate" />
<p:selectOneMenu id="addstate" value="#{addressBean.address.state}" disabled="#{addressBean.disableState}">
<f:selectItem itemLabel="Select State" itemValue="" />
<f:selectItems value="#{addressBean.getStates()}" />
</p:selectOneMenu>
</h:form>
</h:body>
</html>
I have the following files in my application but I can't get the values from the selectOneMenu on file elementoUpdateDialog.xhtml to update the dataTable on gerirElementos.xhtml and sql table.
Where is my error?
elementoUpdateDialog.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:body>
<p:dialog widgetVar="elementoUpdateDialogWidget"
id="elementoUpdateDialogId" height="300" width="500" modal="true"
closable="true" draggable="false" resizable="false">
<h:form id="elementoUpdateDialogForm" prependId="false">
<h:panelGrid columns="2">
<h:outputText value="elementoID" />
<h:inputText value="#{elementoMB.elemento.elementoId}"
required="true" label="elementoID" />
<h:outputText value="Posto" />
<h:outputText value="#{elementoMB.elemento.posto.postoId}" />
<h:selectOneMenu value="#{postoMB.posto.postoId}">
<f:selectItems value="#{postoMB.allPostos}" var ="posto"
itemLabel="#{postoMB.posto.posto}" itemValue="# {elementoMB.elemento.posto.postoId}"/>
</h:selectOneMenu>
<br />
<h:outputText value="Classe" />
<h:outputText value="#{elementoMB.elemento.classe.classeId}" />
<h:selectOneMenu value="# {elementoMB.elemento.classe.classeId}">
<f:selectItems value="#{classeMB.allClasses}"/>
<f:selectItem itemValue="# {elementoMB.elemento.classe.classeId}" itemLabel="#{elementoMB.elemento.classe.classeId}"/>
</h:selectOneMenu>
<br/>
<h:outputText value="Nome" />
<h:inputText value="#{elementoMB.elemento.nome}" required="true"
label="Nome" />
<h:outputText value="NII" />
<h:inputText value="#{elementoMB.elemento.NII}" required="true"
label="NII" />
<p:commandButton value="Gravar" icon="ui-icon-plus"
action="#{elementoMB.updateElemento()}"
update=":messageGrowl :elementosForm:elementosTable"
oncomplete="closeDialogIfSucess(xhr, status, args, elementoUpdateDialogWidget, 'elementoUpdateDialogId')" />
<p:commandButton value="Cancelar" icon="ui-icon-cancel"
actionListener="#{elementoMB.resetElemento()}"
onclick="elementoUpdateDialogWidget.hide();" type="button" />
</h:panelGrid>
</h:form>
</p:dialog>
</h:body>
</html>
gerirElementos.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<ui:composition template="/pages/protected/templates/master.xhtml">
<ui:define name="divMain">
<p:menubar>
<p:submenu label="Elementos" icon="ui-icon-contact">
<p:menuitem value="Listar"
url="/pages/protected/defaultUser/gerirElementos.xhtml" />
</p:submenu>
<p:submenu label="Classes" icon="ui-icon-contact">
<p:menuitem value="Listar"
url="/pages/protected/admin/gerirClasses.xhtml" />
</p:submenu>
<p:submenu label="Postos" icon="ui-icon-contact">
<p:menuitem value="Listar"
url="/pages/protected/admin/gerirPostos.xhtml" />
</p:submenu>
<p:submenu label="RegistoSarPerm" icon="ui-icon-contact">
<p:menuitem value="Listar"
url="/pages/protected/defaultUser/gerirRegistoSarPerm.xhtml" />
</p:submenu>
</p:menubar>
<h:form id="elementosForm">
<p:dataTable id="elementosTable" var="elemento"
value="#{elementoMB.allElementos}" paginator="true" rows="10"
selepaginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="1,5,10">
<f:facet name="header">
Lista de Elementos
</f:facet>
<p:column headerText="NII" sortBy="nii" id="nii">
#{elemento.NII}
</p:column>
<p:column headerText="Posto" sortBy="posto" id="posto">
#{elemento.posto.posto}
</p:column>
<p:column headerText="Classe" sortBy="classe" id="classe">
#{elemento.classe.classe}
</p:column>
<p:column headerText="Nome" sortBy="nome" id="nome">
#{elemento.nome}
</p:column>
<p:column>
<p:spacer width="10px" />
<p:commandButton value="Editar" icon="ui-icon-pencil"
update=":elementoUpdateDialogForm"
onclick="elementoUpdateDialogWidget.show();">
<f:setPropertyActionListener target="#{elementoMB.elemento}"
value="#{elemento}" />
</p:commandButton>
<p:spacer width="10px" />
<p:commandButton value="Eliminar" icon="ui-icon-trash"
update=":elementoDeleteDialogForm"
onclick="elementoDeleteDialogWidget.show();">
<f:setPropertyActionListener target="#{elementoMB.elemento}"
value="#{elemento}" />
</p:commandButton>
<p:spacer width="10px" />
</p:column>
</p:dataTable>
<p:commandButton value="Novo Elemento" icon="ui-icon-plus"
actionListener="#{elementoMB.resetElemento()}"
onclick="elementoCreateDialogWidget.show();" />
</h:form>
<ui:include
src="/pages/protected/defaultUser/dialogs/elementoCreateDialog.xhtml" />
<ui:include
src="/pages/protected/defaultUser/dialogs/elementoUpdateDialog.xhtml" />
<ui:include
src="/pages/protected/defaultUser/dialogs/elementoDeleteDialog.xhtml" />
</ui:define>
</ui:composition>
</h:body>
</html>
Elemento.java
package com.model;
import java.io.Serializable;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
#Entity
#Table(name="Elemento")
public class Elemento implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="elementoId")
private int elementoId;
#ManyToOne
#JoinColumn(name = "classeId")
private Classe classe;
#ManyToOne
#JoinColumn(name="postoID")
private Posto posto;
#Column(name="NII")
private String NII;
#Column(name="nome")
private String nome;
public Elemento(){
}
public Elemento(String NII, String nome){
this.NII = NII;
this.nome = nome;
}
//Getters and Setters
public int getElementoId() {
return elementoId;
}
public void setElementoId(int elementoId) {
this.elementoId = elementoId;
}
public String getNII() {
return NII;
}
public void setNII(String nII) {
NII = nII;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public Classe getClasse() {
return classe;
}
public void setClasse(Classe classe) {
this.classe = classe;
}
public Posto getPosto() {
return posto;
}
public void setPosto(Posto posto) {
this.posto = posto;
}
#Override
public int hashCode() {
return elementoId;
}
#Override
public boolean equals(Object obj) {
if (obj instanceof Elemento) {
Elemento elemento = (Elemento) obj;
return elemento.getElementoId() == elementoId;
}
return false;
}
}
ElementoMB.java
package com.mb;
import java.io.Serializable;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import com.facade.ElementoFacade;
import com.model.Classe;
import com.model.Elemento;
import com.model.Posto;
#ViewScoped
#ManagedBean
public class ElementoMB extends AbstractMB implements Serializable {
private static final long serialVersionUID = 1L;
private Posto posto;
private Classe classe;
private Elemento elemento;
private List<Elemento> elementos;
private ElementoFacade elementoFacade;
public void createElemento() {
try {
getElementoFacade().createElemento(elemento);;
closeDialog();
displayInfoMessageToUser("Created With Sucess");
loadElementos();
resetElemento();
} catch (Exception e) {
keepDialogOpen();
displayErrorMessageToUser("Ops, we could not create. Try again later");
e.printStackTrace();
}
}
public void updateElemento() {
try {
getElementoFacade().updateElemento(elemento);
closeDialog();
displayInfoMessageToUser("Updated With Sucess");
loadElementos();
resetElemento();
} catch (Exception e) {
keepDialogOpen();
displayErrorMessageToUser("Ops, we could not create. Try again later");
e.printStackTrace();
}
}
public void deleteElemento() {
try {
getElementoFacade().deleteElemento(elemento);
closeDialog();
displayInfoMessageToUser("Deleted With Sucess");
loadElementos();
resetElemento();
} catch (Exception e) {
keepDialogOpen();
displayErrorMessageToUser("Ops, we could not create. Try again later");
e.printStackTrace();
}
}
public List<Elemento> getAllElementos(){
if (elementos == null){
loadElementos();
}
return elementos;
}
public ElementoFacade getElementoFacade() {
if (elementoFacade == null) {
elementoFacade = new ElementoFacade();
}
return elementoFacade;
}
public Elemento getElemento() {
if (elemento == null) {
elemento = new Elemento();
}
return elemento;
}
public void setElemento(Elemento elemento) {
this.elemento = elemento;
}
private void loadElementos() {
elementos = getElementoFacade().listAll();
}
public void resetElemento() {
elemento = new Elemento();
}
public Posto getPosto() {
if (posto == null){
posto = new Posto();
}
return posto;
}
public void setPosto(Posto posto) {
this.posto = posto;
}
public Classe getClasse() {
if (classe == null) {
classe = new Classe();
}
return classe;
}
public void setClasse(Classe classe) {
this.classe = classe;
}
public void resetClasse() {
classe = new Classe();
}
}
ElementoFacade.java
package com.facade;
import java.io.Serializable;
import java.util.List;
import com.dao.ElementoDAO;
import com.model.Elemento;
public class ElementoFacade implements Serializable {
private static final long serialVersionUID = 1L;
private ElementoDAO elementoDAO = new ElementoDAO();
public void createElemento(Elemento elemento) {
elementoDAO.beginTransaction();
elementoDAO.save(elemento);
elementoDAO.commitAndCloseTransaction();
}
public void updateElemento(Elemento elemento) {
elementoDAO.beginTransaction();
Elemento persistedElemento = elementoDAO.find(elemento.getElementoId());
persistedElemento.setNome(elemento.getNome());
persistedElemento.setNII(elemento.getNII());
elementoDAO.commitAndCloseTransaction();
}
public void deleteElemento(Elemento elemento){
elementoDAO.beginTransaction();
Elemento persistedElementoWithIdOnly = elementoDAO.findReferenceOnly(elemento.getElementoId());
elementoDAO.delete(persistedElementoWithIdOnly);
elementoDAO.commitAndCloseTransaction();
}
public Elemento findElemento(int elementoId) {
elementoDAO.beginTransaction();
Elemento elemento = elementoDAO.find(elementoId);
elementoDAO.closeTransaction();
return elemento;
}
public List<Elemento> listAll() {
elementoDAO.beginTransaction();
List<Elemento> result = elementoDAO.findAll();
elementoDAO.closeTransaction();
return result;
}
}
Here,
<f:selectItems value="#{postoMB.allPostos}" var="posto"
itemLabel="#{postoMB.posto.posto}" itemValue="#{elementoMB.elemento.posto.postoId}"/>
Your itemLabel and itemValue attributes, representing the current option label and value, are wrong. They're for some unclear reason referencing a backing bean property instead of the currently iterated option object as definied in var="posto".
Fix it accordingly:
<f:selectItems value="#{postoMB.allPostos}" var="posto"
itemLabel="#{posto.postoId}" itemValue="#{posto}"/>
This should display the items correctly.
And here,
<h:selectOneMenu value="#{postoMB.posto.postoId}">
the selected item is wrong. This would only cause problems during submitting and during displaying a preselected item. You should refer the very same type as itemValue itself, not some ID (otherwise you're changing only the id of an entity instead of the entity itself, resulting in major potential trouble as those are references):
<h:selectOneMenu value="#{postoMB.posto}">
Supply if necessary a converter in case you don't have a #FacesConverter(forClass=Posto.class).
Apply the same lesson learnt on the other <h:selectOneMenu> you've there.
See also:
Our <h:selectOneMenu> wiki page
How to populate options of h:selectOneMenu from database?