In my xhtml page i have two dependant selectOneMenu, with the second one being filled in an ajax call. Here's the jsf code fragment:
<h:panelGrid columns="2" cellpadding="5">
<h:outputLabel value="Dirección:" for="direccion"/>
<p:inputText id="direccion" value="#{datosInstitucion.institucion.direccion}" required="true" label="Dirección"/>
<h:outputLabel value="Departamento:" for="departamento"/>
<p:selectOneMenu id="departamento" value="#{datosInstitucion.idDepartamento}" required="true" label="Departamento">
<f:selectItem itemLabel="Seleccione el departamento" itemValue="#{null}"/>
<c:forEach items="#{datosInstitucion.departamentos}" var="departamento">
<f:selectItem itemLabel="#{departamento.nombre}" itemValue="#{departamento.id}"/>
</c:forEach>
<f:ajax render="municipio" listener="#{datosInstitucion.cargarMunicipios()}"/>
</p:selectOneMenu>
<h:outputLabel value="Municipio:" for="municipio"/>
<p:selectOneMenu id="municipio" value="#{datosInstitucion.idMunicipio}" required="true" label="Municipio">
<f:selectItem itemLabel="Seleccione el municipio" itemValue="#{null}"/>
<c:forEach items="#{datosInstitucion.municipios}" var="municipio">
<f:selectItem itemLabel="#{municipio.nombre}" itemValue="#{municipio.id}"/>
</c:forEach>
</p:selectOneMenu>
</h:panelGrid>
This fragment of code is inside a primefaces wizard component, so when the 'next' button is pressed a validation error is caused for the second selectOneMenu even when there's a value set.
What could be causing this behavior?
Relevant backing bean code:
#ManagedBean(name = "datosInstitucion")
#ViewScoped
public class DatosInstitucion implements Serializable{
#EJB
private Instituciones instituciones;
#EJB
private Parametros parametros;
#Inject
private Mensajes mensajes;
private List<Departamento> departamentos;
private List<Municipio> municipios;
private Map<Integer, Departamento> mapaDepartamentos;
private Integer idDepartamento;
private Integer idMunicipio;
private Institucion institucion;
#PostConstruct
private void inicializar(){
this.mapaDepartamentos = new HashMap<>();
this.departamentos = parametros.consultarDepartamentos();
for(Departamento departamento : departamentos){
this.mapaDepartamentos.put(departamento.getId(), departamento);
}
this.prepararInstitucion();
}
private void prepararInstitucion(){
this.institucion = new Institucion();
this.institucion.setResponsable(new Persona());
}
public Institucion getInstitucion() {
return institucion;
}
public List<Departamento> getDepartamentos(){
return departamentos;
}
public TipoIdentificacion[] getTiposIdentificacion(){
return TipoIdentificacion.deResponsables();
}
public Integer getIdDepartamento() {
return idDepartamento;
}
public void setIdDepartamento(Integer idDepartamento) {
this.idDepartamento = idDepartamento;
}
public Integer getIdMunicipio() {
return idMunicipio;
}
public void setIdMunicipio(Integer idMunicipio) {
this.idMunicipio = idMunicipio;
}
public void cargarMunicipios(){
idMunicipio = null;
if(idDepartamento != null){
this.municipios = mapaDepartamentos.get(idDepartamento).getMunicipios();
}else{
this.municipios = Collections.emptyList();
}
}
public List<Municipio> getMunicipios() {
return municipios;
}
public void confirmar(){
this.instituciones.guardar(institucion);
this.mensajes.exito("La institución ha sido registrada en el sistema");
this.prepararInstitucion();
}
}
This is because you are using JSTL <c:foreach> with JSF. The life cycle of JSTL vs JSF matters. JSTL is executed when the view is being built, while JSF is executed when the view is being rendered. The two do not work in synch with each other. In your case, you need to use <f:selectItems> instead of <c:foreach>
Replace:
<c:forEach items="#{datosInstitucion.municipios}" var="municipio">
<f:selectItem itemLabel="#{municipio.nombre}" itemValue="#{municipio.id}"/>
</c:forEach>
with:
<f:selectItems value="#{datosInstitucion.municipios}"
var="municipio" itemLabel="#{municipio.nombre}"
itemValue="#{municipio.id}"/>
For more reading, I suggest you to read the following answer
Related
I am trying to create a simple jsf page where I have a dropdown whose value determines which label to render. Initially all the labels' render is set as false through the backing bean constructor. But I have called submit onchange which sets the respective values to true for the labels. I have set the scope of the backing bean as session so that the value being set does not get removed onchange. However the label does not get rendered onchange. Below is the code snippet for the jsf page:
<h:form>
<h:panelGroup>
<h:outputLabel styleClass="captionOutputField" value="Select Report Type:" />
<h:selectOneMenu id="selectedMenu" onchange="submit()" valueChangeListener="#{ReportHealth.typeSelectDropDownChange}">
<f:selectItem itemLabel="" itemValue="empty" />
<f:selectItem itemLabel="daily" itemValue="daily" />
<f:selectItem itemLabel="weekly" itemValue="weekly" />
<f:selectItem itemLabel="monthly" itemValue="monthly" />
</h:selectOneMenu>
<h:panelGroup rendered="#{ReportHealth.daily}">
<h3>MENU 0</h3>
</h:panelGroup>
<h:panelGroup rendered="#{ReportHealth.weekly}">
<h3>MENU 1</h3>
</h:panelGroup>
<h:panelGroup rendered="#{ReportHealth.monthly}">
<h3>MENU 2</h3>
</h:panelGroup>
Here is the backing bean:
public class ReportHealth implements Serializable{
private static final long serialVersionUID = 1L;
private boolean weekly;
private boolean monthly;
private boolean daily;
private String menuValue;
public ReportHealth() {
weekly = false;
monthly = false;
daily = false;
}
public String getMenuValue() {
return menuValue;
}
public void setMenuValue(String menuValue) {
this.menuValue = menuValue;
}
public boolean isWeekly() {
return weekly;
}
public void setWeekly(boolean weekly) {
this.weekly = weekly;
}
public boolean isMonthly() {
return monthly;
}
public void setMonthly(boolean monthly) {
this.monthly = monthly;
}
public boolean isDaily() {
return daily;
}
public void setDaily(boolean daily) {
this.daily = daily;
}
public void typeSelectDropDownChange(ValueChangeEvent e)
{
String typeSelectVal = e.getNewValue().toString();
if(typeSelectVal!=null && typeSelectVal.equalsIgnoreCase("daily"))
{
setDaily(true);
setWeekly(false);
setMonthly(false);
}
else if(typeSelectVal!=null && typeSelectVal.equalsIgnoreCase("weekly"))
{
setDaily(false);
setWeekly(true);
setMonthly(false);
}
else if(typeSelectVal!=null && typeSelectVal.equalsIgnoreCase("monthly"))
{
setDaily(false);
setWeekly(false);
setMonthly(true);
}
else
{
setDaily(false);
setWeekly(false);
setMonthly(false);
}
}
}
I dont understand why you are using so complicated code for simple task.
Here is what you need
<h:form>
<h:panelGroup>
<h:outputLabel styleClass="captionOutputField" value="Select Report Type:"/>
<h:selectOneMenu id="selectedMenu" value="#{reportHealth.menuValue}">
<f:selectItem itemLabel="" itemValue="empty" />
<f:selectItem itemLabel="daily" itemValue="daily" />
<f:selectItem itemLabel="weekly" itemValue="weekly" />
<f:selectItem itemLabel="monthly" itemValue="monthly" />
<f:ajax render="#form">
</f:ajax>
</h:selectOneMenu>
<h:panelGroup rendered="#{reportHealth.menuValue eq 'daily'}">
<h3>MENU 0</h3>
</h:panelGroup>
<h:panelGroup rendered="#{reportHealth.menuValue eq 'weekly'}">
<h3>MENU 1</h3>
</h:panelGroup>
<h:panelGroup rendered="#{reportHealth.menuValue eq 'monthly'}">
<h3>MENU 2</h3>
</h:panelGroup>
</h:panelGroup>
</h:form>
and Bean will be
#ManagedBean
#ViewScoped
public class ReportHealth implements Serializable{
private static final long serialVersionUID = 1L;
private String menuValue;
public String getMenuValue() {
return menuValue;
}
public void setMenuValue(String menuValue) {
this.menuValue = menuValue;
}
}
I found out what was wrong with my code. Instead of putting the labels in <H3>tags. I needed to put it in <h:outputText> tag.
I'm working on a small course passing project, and I have a problem.
The manager.xhtml is a JSF page, it is used to view the data from database, sort them, filter them, delete entries and edit those entries. When I'm using #ViewScoped in Manager.java - everything EXCEPT the edit part works just fine. The "Edit" link is sending the user to another page - edit.xhtml. After I used #ConversationScoped to be able to read data send from manager.xhml in edit.xhtml. After using #ConversationScoped the entry editing option worked flawlessly, but it started making errors in some of the filtering/sorting options - sorting by CATEGORY started pulling out errors like "Name is null", filtering by price - the same.
Here is the code.
manager.xhtml
Here is the form in which the problems start to occur while using #ConversationScoped
<h:form>
<h:panelGrid id="filterPanel" columns="7">
<f:ajax render="filterValue" event="change" execute="filterValue">
#{text.sort}
<h:selectOneMenu value="#{manager.order}">
<f:selectItem itemValue="cargoName" itemLabel="#{text.cargo_name}"/>
<f:selectItem itemValue="price" itemLabel="#{text.cargo_price}"/>
<f:selectItem itemValue="category" itemLabel="#{text.cargo_category}"/>
</h:selectOneMenu>
<h:selectOneMenu id="filterType" value="#{manager.filterType}">
<f:selectItem itemValue="CARGO_NAME" itemLabel="#{text.cargo_name}"/>
<f:selectItem itemValue="PRICE" itemLabel="#{text.cargo_price_filter}"/>
<f:selectItem itemValue="CATEGORY" itemLabel="#{text.cargo_category}"/>
</h:selectOneMenu>
<h:panelGroup id="filterValue">
<h:panelGroup id="filterValues">
<h:inputText id="filterValueInput" value="#{manager.filterValue}" rendered="#{manager.filterType == 'CARGO_NAME'
or manager.filterType == 'PRICE'}"
required="#{manager.filterType == 'PRICE'}"/>
<h:message for="filterValueInput"/>
<h:inputText id="filterValueInput2" value="#{manager.filterValue2}" rendered="#{manager.filterType == 'PRICE'}"
required="#{manager.filterType == 'PRICE'}"/>
<h:message for="filterValueInput2"/>
</h:panelGroup>
<h:selectOneMenu id="cargoForm" value="#{manager.filterValue}" rendered="#{manager.filterType == 'CATEGORY'}">
<f:selectItem itemLabel="#{text.cargo_text_BOOKS}" itemValue="BOOKS"/>
<f:selectItem itemLabel="#{text.cargo_text_CALENDARS}" itemValue="CALENDARS"/>
<f:selectItem itemLabel="#{text.cargo_text_CD}" itemValue="CD"/>
<f:selectItem itemLabel="#{text.cargo_text_EBOOKS}" itemValue="EBOOKS"/>
<f:selectItem itemLabel="#{text.cargo_text_OFFICE}" itemValue="OFFICE"/>
<f:selectItem itemLabel="#{text.cargo_text_VINYL}" itemValue="VINYL"/>
</h:selectOneMenu>
</h:panelGroup>
</f:ajax>
<h:commandButton action="#{manager.filter}" value="#{text.button_refresh}"/>
<h:commandButton action="#{manager.reset}" value="#{text.button_reset}"/>
</h:panelGrid>
edit.xhtml
The edition form - it's filled with the data of selected entry ONLY when using #ConversationScoped:
Getting the ID sent by manager.xhtml
<h:inputHidden value="#{manager.editCargo.id}"/>
In the form the data is taken from manager like this:
<h:inputText id="cargoName" value="#{manager.editCargo.cargoName}" required="true">
</h:inputText>
button to save changes:
<h:commandButton value="#{text.edit_button}" action="#{manager.update}"/>
Manager.java - unnecesary code removed.
#ConversationScoped
#ManagedBean
public class Manager implements Serializable {
#Inject
private CargoRepository repository; // tworzy nową instancję objektu CargoRepository
private List<Cargo> cargos; // tworzy listę obiektów Cargo
private String order = CARGO_NAME; // musi istnieć by zainicjować jakąś zmienną order, ponieważ manager.xhtml już na starcie sortuje po order więc nie może być null.
private FilterType filterType = FilterType.CARGO_NAME;
private String filterValue;
private String filterValue2;
#Inject
private Conversation conversation;
Getters and setters removed...
#PostConstruct
public void init() {
cargos = repository.getAll(order);
editCargo = new Cargo();
}
public void filter() {
if (filterType == FilterType.PRICE) {
cargos = repository.getAll(filterType, filterValue, filterValue2, order);
} else {
cargos = repository.getAll(filterType, filterValue, order);
}
}
public void resetFilterValue() {
filterValue = "";
filterValue2 = "";
}
public String edit(Cargo cargo) {
conversation.start();
editCargo = cargo;
return "edit";
}
public String update() {
conversation.end();
repository.update(editCargo);
System.out.println(editCargo.toString());
init();
return "manager";
}
}
I've managed to repair the problem.
Instead of:
#ConversationScoped
#ManagedBean
I have used
#Named
#SessionScoped
The #SessionScoped was imported from
import javax.enterprise.context.SessionScoped;
I removed EVERYTHING related to #ConversationScoped including
#Inject
private Conversation conversation;
and every usage of
conversation.start();
conversation.end();
Everything is working flawlessly now.
i have a sample selectOneMenu that have List of date and date as values but when i try to validate i have it red i will show you my sample example :
my managed bean :
#ManagedBean
#SessionScoped
public class Testbean {
#EJB
private ManageOfPlanifieLocal manageOfPlanifie;
List<Date> listdate = new ArrayList<Date>();
Date newdate;
#PostConstruct
public void initialize() {
listdate=manageOfPlanifie.retournerdatedesplanif();;
}
public String gototest2(Date date)
{
return "test2.xhtml?faces-redirect=true";
}
public List<Date> getListdate() {
return listdate;
}
public void setListdate(List<Date> listdate) {
this.listdate = listdate;
}
public Date getNewdate() {
return newdate;
}
public void setNewdate(Date newdate) {
this.newdate = newdate;
}
}
and this is my two jsf pages :
test1.xhtml
<h:outputLabel for="dateplanif" value="date de planification : " />
<p:selectOneMenu id="dateplanif" value="#{ testbean.newdate}">
<f:selectItems value="#{testbean.listdate}" var="da" itemValue="#{da}" />
</p:selectOneMenu>
<p:commandButton value="suivant" style="color:black;" action="#{testbean.gototest2(testbean.listdate)}" update="#form" />
test2.xhtml
<h2>Choix de l'equipe</h2>
<h:outputText value="Date : "/>
<h:outputText value="#{ testbean.newdate}"/>
the problem i do sample transfer of data with out converstion just simple and i get that :
do you know i have it red and i cant move to the next page ??
When you have a list of Objects, you need to convert them, so that setting the value works properly. Try the following code.
<p:selectOneMenu id="dateplanif" value="#{testbean.newdate}">
<f:selectItems value="#{testbean.listdate}" var="da" itemValue="#{da}" />
<f:convertDateTime pattern="dd-MM-yyyy" />
</p:selectOneMenu>
I am able to render dynamic but don't know how to get those dynamically created values in back end.
test.xhtml
<h:form>
Insert Your Desire Number : <h:inputText value="#{bean.number}">
<f:ajax listener="#{bean.submitAjax}" execute="#form" render="#form" event="keyup" />
</h:inputText>
<br></br>
<h:outputText value="#{bean.text}" />
<h:dataTable value="#{bean.items}" var="item">
<h:column>
<h:inputText value="#{item.value}" />
</h:column>
</h:dataTable>
<h:commandButton value="Submit" action="#{item.submit}" />
</h:form>
If I render 3 input boxes, and when I submit the button i get the last value only, Can someone guide me how can i
Bean.java
#ManagedBean(name="bean")
#SessionScoped
public class Bean {
private int number;
private List<Item> items;
private Item item;
//getter and setter are omitted
public void submitAjax(AjaxBehaviorEvent event)
{
items = new ArrayList<Item>();
for (int i = 0; i < number; i++) {
items.add(new Item());
}
}
}
Item.java
private String value;
//getter and setter are omitted
public void submit() {
System.out.println("Form Value : "+value);
}
Your submit() method is in the wrong place. You should put it on the managed bean, not on the entity.
Thus so,
<h:commandButton value="Submit" action="#{bean.submit}" />
with
public void submit() {
for (Item item : items) {
System.out.println(item.getValue());
}
}
or more formally,
#EJB
private ItemService service;
public void submit() {
service.save(items);
}
it seems as if it is not possible to disable items in a SelectOneMenu from PrimeFaces (3.3) when using the custom content (as shown at http://www.primefaces.org/showcase-labs/ui/selectOneMenu.jsf).
The testcase is simple, just take the following:
<h:form>
<p:selectOneMenu value="#{testBean.selected}">
<f:selectItems value="#{testBean.options}" var="t"
itemLabel="#{t.label}" itemValue="#{t}"
itemDisabled="#{t.value % 2 == 0 ? 'true' : 'false'}" />
</p:selectOneMenu>
<p:selectOneMenu value="#{testBean.selected}" var="x">
<f:selectItems value="#{testBean.options}" var="t"
itemLabel="#{t.label}" itemValue="#{t}"
itemDisabled="#{t.value % 2 == 0 ? 'true' : 'false'}" />
<p:column>
#{x.label} -- #{x.label}
</p:column>
</p:selectOneMenu>
</h:form>
and the following Java files:
Bean:
#Named
public class TestBean {
private TestObject selected;
// getter/setter
public List<TestObject> getOptions() {
return Arrays.asList(new TestObject("1"), new TestObject("2")); }
}
Object:
public class TestObject {
private Integer value;
// getter/setter
public TestObject() {}
public TestObject(String s) {
this.setLabel(s);
}
public String getLabel() {return "label: " + value;}
public void setLabel(String l) {this.value = new Integer(l);}
}
The first dropdown works fine, the second one doesn't. Any idea on how to solve that?