selectOneMenu выбранное значение
Ну, мне нужно кое-что прояснить по тегу selectOneMenu, используя выражение EL для получения / установки значений
<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>
У меня есть этот код, он отображает список, содержащий ("- Выберите вариант--", Вариант 1, Вариант 2, ... Вариант n) Когда я нажимаю на Вариант, я ожидал бы selectedVariant
недвижимость в missionHandler
managedBean будет обновляться автоматически. Но это не так. variantConverter
конвертер даже не вызывается для преобразования String "variable.commercialName" в реальное Variant
объект. Вариант объекта реализует hashCode()
а также equals()
- Какую концепцию выражения / тега EL мне не хватает?
Что бы решить мою проблему с обновлением?
РЕДАКТИРОВАТЬ: managedBean (упрощенный)
@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; }
}
конвертер
@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();
}
}
и файл 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: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>
3 ответа
Пара замечаний по вашему коду:
Делать вещи в конструкторе управляемого бина == плохой дизайн, использовать
@PostConstructor
вместо.Создание экземпляра DAO вручную в вашем конвертере == плохой дизайн. В идеале, ваш DAO должен быть управляемым объектом (предпочтительно EJB), который вы можете вставить в конвертер. Быть управляемым объектом означает, что (теоретически) он, вероятно, будет одноэлементным и правильно управляется контейнером. По крайней мере, таким образом, вы не будете чувствовать себя плохо об этом.
Попытка вручную управлять конвертером. Объявите конвертер как отдельный компонент и дайте контейнеру выполнить свою работу, чтобы избежать ненужной отладки.
variantsMenu
к нему не прикреплен обработчик ajax, поэтому вы не получите обновленного значения в компоненте поддержки, пока не будет отправлена вся форма<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>
Значение в управляемом bean-компоненте не обновляется напрямую при выборе элемента в меню, поскольку форма не была отправлена.
Либо отправьте его через <h:commandButton ...>
или используйте событие ajax <f:ajax event="change" ...>
в меню.
Если я что-то упустил, я не думаю, что вы когда-либо создавали свой конвертер. Вы привязываетесь к бобу, чтобы получить конвертер, но где это значение?
Я могу понять, что вы не любите доступ к базе данных в конвертере. Это почти никогда не требуется, если вы используете один из конвертеров элементов выбора в OmniFaces.