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?
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.
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
I want to implement a filtering facility in a JSF web application as follows: The users can add as many filters as they want. They can also delete them. So I am having a dataTable of filters. Each row consists of one h:selectOneMenu which has an ajax “change” event in order to make a second h:selectOneMenu visible in the same row. The options of the second h:selectOneMenu are calculated dynamically according to the selected option of the first.
The problem is that the value of second h:selectOneMenu is never set to the back-end object even if I added an ajax event. However the value of the first h:selectOneMenu is set.
I have the following fragment of code in an .xhtml page:
<h:form id="filterForm">
<h:dataTable id="filterTable" value="#{filterManager.filters}" var="filter">
<h:column>
<h:outputLabel value="#{msgs.filterBy}:" for="availableFilters" />
<h:selectOneMenu id="availableFilters" value="#{filter.filter}">
<f:selectItems value="#{filterManager.getProperties(typeSelector.typeSelected)}" />
<f:ajax event="change" render=":filterForm" />
</h:selectOneMenu>
</h:column>
<h:column>
<h:panelGroup id="filterValuesPanel" >
<h:outputLabel value="#{msgs.value}:" for="filterValues" rendered="#{!filter.filterEmpty}" />
<h:selectOneMenu value="#{filter.value}" id="filterValues" rendered="#{!filter.filterEmpty}" >
<f:selectItems value="#{filterManager.getPossibleAnswers(filter)}" />
<f:ajax event="change" render=":filterForm" />
</h:selectOneMenu>
</h:panelGroup>
</h:column>
<h:column>
<h:commandButton value="#{msgs.delete}" title="#{msgs.deleteFilter}">
<f:ajax event="click" listener="#{filterManager.removeFilter(filter)}" render=":filterForm" />
</h:commandButton>
</h:column>
</h:dataTable>
<h:commandButton value="#{msgs.addNewFilter}">
<f:ajax event="click" listener="#{filterManager.addNewFilter}" render=":filterForm" />
</h:commandButton>
</h:form>
I have a bean called “FilterManager” which has a ViewScoped. Important parts are shown below:
#ManagedBean
#ViewScoped
public class FilterManager implements Serializable {
private List<Filter> filters; // it has a getter
private int currentFilterId;
public void addNewFilter(AjaxBehaviorEvent event) {
this.currentFilterId++;
this.filters.add(Filter.getEmptyFilter(this.currentFilterId));
}
public void removeFilter(Filter filter) {
this.filters.remove(filter);
}
...
}
The Filter class is a normal class (not a bean) and is shown below:
public class Filter implements Serializable {
private int id;
private String filter;
private String value;
public String getFilter() {
return filter;
}
public void setFilter(String theFilter) {
if (theFilter != null && !theFilter.isEmpty())
this.filter = theFilter;
}
public String getValue() {
return value;
}
public void setValue(String theValue) {
this.value = theValue;
}
public boolean isFilterEmpty() {
return this.filter == null || this.filter.isEmpty();
}
...
}
Notice that TypeSelector is a SessionScoped bean which has a typeSelected property along with getter and setter.
The problem is: filter.filter is set correctly whereas filter.value is never set. I can't find the problem so I need your help please. Apologies for all this code but I needed to provide you with all the necessary details.
Thanks in advance!
Okay guys that was my fault. I had a bug in FilterManager.getPossibleAnswers(Filter filter) method. Basically, at the end of the method, I was setting filter.value to the first element of List unconditionally. Eg instead of writing
if (filter.getValue() == null || filter.getValue().isEmpty()) {
SelectItem first = answers.get(0);
filter.setValue((String) first.getValue());
}
I just wrote:
SelectItem first = answers.get(0);
filter.setValue((String) first.getValue());
Although filter.value was updating as normal, the value was changing back to default (first element in list) during re-rendering of dataTable component.
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);
}