selectOneMenu selected value

社会主义新天地 提交于 2019-12-12 17:16:14

问题


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:

  1. Doing stuff in the constructor of the managed bean==bad design, use @PostConstructor instead.

  2. 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.

  3. 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.

  4. 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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!