问题
Well, I need some clarification on selectOneMenu tag, using EL expression to get/set values
<h:selectOneMenu id="variantsMenu"
value="#{missionHandler.selectedVariant}"
converter="#{missionHandler.variantConverter}">
<f:selectItem itemLabel="-- Select a Variant --" />
<f:selectItems value="#{missionHandler.variants}" var="variant"
itemValue="#{variant}" itemLabel="#{variant.commercialName}" />
</h:selectOneMenu>
I have this code, it displays a list containing ("-- Select a Variant--", Variant 1, Variant 2, ... Variant n)
When I click on a Variant, I would expect the selectedVariant
property in the missionHandler
managedBean to be updated automatically. But this is not the case. The variantConverter
converter is not even called to convert the String "variant.commercialName" to a real Variant
object.
The variant object implements hashCode()
and equals()
- What concept of EL expression / tag am I missing ?
What would be the solution to my update problem ?
EDIT : managedBean (simplified)
@ManagedBean @ViewScoped public class MissionHandler implements Serializable { private static final long serialVersionUID = 2462652101518266609L; private List<FlightFeasibilityException> exceptions; @EJB private VariantDao variantDao; private Variant selectedVariant; private List<Variant> variants; private VariantConverter variantConverter; public MissionHandler() { /** Create an empty list of exceptions */ exceptions = new ArrayList<FlightFeasibilityException>(); } @PostConstruct public void init() { System.out.println("init done"); } public List<FlightFeasibilityException> getExceptions() { return exceptions; } public void setExceptions(List<FlightFeasibilityException> exceptions) { this.exceptions = exceptions; } public Variant getSelectedVariant() { return selectedVariant; } public void setSelectedVariant(Variant selectedVariant) { this.selectedVariant = selectedVariant; } public List<Variant> getVariants() { return variants; } public void setVariants(List<Variant> variants) { this.variants = variants; } public VariantConverter getVariantConverter() { return variantConverter; } public void setVariantConverter(VariantConverter variantConverter) { this.variantConverter = variantConverter; }
}
Converter
@FacesConverter(forClass=Variant.class)
public class VariantConverter implements Converter, Serializable {
private static final long serialVersionUID = 7053414108213420057L;
private VariantDao variantDao=new VariantDaoImpl();
@Override
public Object getAsObject(FacesContext context, UIComponent component,
String value) {
System.out.println("convert to Object " + value);
Variant variant = variantDao.find(value);
System.out.println("got variant " + variant.getCommercialName());
return variant;
}
@Override
public String getAsString(FacesContext context, UIComponent component,
Object value) {
System.out.println("convert to String " + value);
return ((Variant) value).getCommercialName();
}
}
and the xhtml file
<!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:h="http://java.sun.com/jsf/html"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>Mission Page</title>
<link href="./css/styles.css" rel="stylesheet" type="text/css" />
</h:head>
<h:body>
<rich:panel>
<f:facet name="header">
Mission Information
</f:facet>
<a4j:outputPanel layout="block">
<h:form>
<h:outputText style="font-weight: bold;" value="Mission Id: " />
<h:inputText id="missionId" label="missionId"
value="#{missionHandler.mission.id}" disabled="true"
style=" width : 50px;">
</h:inputText>
<h:outputText style="font-weight: bold;" value="Mission Status: " />
<h:inputText id="missionStatus" label="missionStatus"
value="#{missionHandler.mission.status}" disabled="true">
</h:inputText>
</h:form>
<br />
<h:form>
<h:selectOneMenu value="#{missionHandler.selectedAircraftType}"
converter="#{missionHandler.acTypeConverter}">
<f:selectItem itemLabel="-- Select an A/C Type --" />
<f:selectItems value="#{missionHandler.aircraftTypes}" var="type"
itemValue="#{type}" itemLabel="#{type.typeOACI}" />
<f:ajax listener="#{missionHandler.changeSelectedAircraftType}"
render="@form" />
</h:selectOneMenu>
<h:selectOneMenu id="variantsMenu"
value="#{missionHandler.selectedVariant}"
converter="#{missionHandler.variantConverter}"
rendered="#{not empty missionHandler.selectedAircraftType}">
<f:selectItem itemLabel="-- Select a Variant --" />
<f:selectItems value="#{missionHandler.variants}" var="variant"
itemValue="#{variant}" itemLabel="#{variant.commercialName}" />
</h:selectOneMenu>
</h:form>
</a4j:outputPanel>
</rich:panel>
….. A LOT OF OTHER THINGS …..
</h:body>
</html>
回答1:
A couple of notes on your code:
Doing stuff in the constructor of the managed bean==bad design, use
@PostConstructor
instead.Manually instantiating the DAO in your converter==bad design. Ideally, your DAO should be a managed object(preferably an EJB) that you can inject into the converter. Being a managed object means it would (in theory) probably be a singleton and managed properly by the container. At least this way, you won't feel bad about it.
Trying to manually manage the converter. Declare the converter as a standalone component and let the container do it's work so you can avoid unnecessary debugging.
variantsMenu
does not have an ajax handler attached to it so you won't get the value updated in the backing bean until the entire form is submitted<h:selectOneMenu id="variantsMenu" value="#{missionHandler.selectedVariant}" converter="#{variantConverter}" rendered="#{not empty missionHandler.selectedAircraftType}"> <f:ajax listener="#{missionHandler.changeVariant}" render="@form" /> <f:selectItem itemLabel="-- Select a Variant --" /> <f:selectItems value="#{missionHandler.variants}" var="variant" itemValue="#{variant}" itemLabel="#{variant.commercialName}" /> </h:selectOneMenu>
回答2:
The value in the managed bean is not directly updated when you select an item from the menu because the form was not submitted.
Either submit it via a <h:commandButton ...>
or use an ajax event <f:ajax event="change" ...>
within the menu.
回答3:
Unless I'm missing something, I don't think you ever instantiate your converter. You bind to a bean to get the converter, but where's the value?
I can understand you're not fond about the database access in the converter. It's almost never necessary to do this if you make use of one of the select item converters in OmniFaces.
来源:https://stackoverflow.com/questions/15076178/selectonemenu-selected-value