Почему selectOneMenu отправляет ItemLabel в конвертер?
моя страница JSF
<h:form>
<h:selectOneMenu id="studlist" value="#{studBean.selectedStudent}">
<p:ajax event="change" process="studlist" update="studdep" ></p:ajax>
<f:selectItems value="#{studBean.student}" var="s"
itemValue="#{s.studid}" itemLabel="#{s.name}"/>
<f:converter converterId="studentconverter"/>
</h:selectOneMenu>
</h:form>
класс преобразователя (StudentConverter)
public Object getAsObject(FacesContext context, UIComponent component, String value) {
Student studConvert= new Student();
List<Student> students=new ArrayList<Student>();
students=(ArrayList<Student>)((UISelectItems
component.getChildren().get(0)).getValue();
}
на этом конверторе значение аргумента Аргумент 'дает itemLabel
Почему это происходит?
i wand itemValue в этой строке
Ответы
Ответ 1
Я не уверен, почему у вас есть метка товара вместо значения элемента внутри getAsObject()
. Возможно, ваш getAsString()
делает это неправильно и возвращает имя студента на основе идентификатора студента.
В любом случае, я могу сказать, что ваш itemValue
определенно не прав.
<h:selectOneMenu id="studlist" value="#{studBean.selectedStudent}">
<f:selectItems value="#{studBean.student}" var="s"
itemValue="#{s.studid}" itemLabel="#{s.name}" />
<f:converter converterId="studentconverter" />
</h:selectOneMenu>
Конвертер предназначен для преобразования между сложным Java-объектом и представлением String, чтобы он мог передаваться как параметр HTTP-запроса. Однако вы указываете идентификатор студента как значение элемента, а не весь объект студента. Вместо этого вам нужно указать весь объект студента. Вы также должны убедиться, что #{studBean.selectedStudent}
ссылается на свойство Student
, а не на свойство Long
, представляющее идентификатор студента.
Когда вы зафиксируете itemValue
следующим образом:
<h:selectOneMenu id="studlist" value="#{studBean.selectedStudent}">
<f:selectItems value="#{studBean.student}" var="s"
itemValue="#{s}" itemLabel="#{s.name}" />
<f:converter converterId="studentconverter" />
</h:selectOneMenu>
и ваш конвертер следующим образом (тривиальные nullchecks опущены):
public String getAsString(FacesContext context, UIComponent component, Object value) {
// This method is called when item value is to be converted to HTTP request parameter.
// Normal practice is to return an unique identifier here, such as student ID.
Student student = (Student) value;
Long id = student.getStudid();
return String.valueOf(id);
}
public Object getAsObject(FacesContext context, UIComponent component, String value) {
// This method is called when HTTP request parameter is to be converted to item value.
// You need to convert the student ID back to Student.
Long id = Long.valueOf(value);
Student student = someStudentService.find(id);
return student;
}
тогда он должен работать.
В качестве альтернативы вы можете сохранить свой itemValue
по своему усмотрению и полностью удалить <f:converter>
, но тогда вам нужно изменить #{studBean.selectedStudent}
, чтобы указать свойство Long
, представляющее идентификатор студента.
Ответ 2
Вам нужно использовать selectitem list в атрибуте f:selecitems
h:selectOneMenu
Ваша страница будет такой:
<h:form>
<h:selectOneMenu id="studlist" value="#{studBean.selectedStudent}">
<p:ajax event="change" process="studlist" update="studdep" ></p:ajax>
<f:selectItems value="#{studBean.studentSelectItemList}" />
<f:converter converterId="studentconverter"/>
</h:selectOneMenu>
</h:form>
На стороне поддержки bean вы должны заполнить selectisem ученикаSelectItemList.
private List<SelectItem> studentSelectItemList;
//fill studentSelectItemList at the appropriate place
studentSelectItemList.add(new SelectItem(studentId,studentName));
После этих настроек у вас должен быть идентификатор студента в качестве значения выбора.
Ответ 3
Сегодня у меня была такая же проблема.
Это вызвано неправильным рендерингом:
<select ...>
<option>None</option>
<option value="1">First</option>
<option value="2">Second</option>
</select>
omitting value=""
для опции "Нет" приводит к отправке метки вместо пустой строки.
Однако для решения этой проблемы и сделайте рендерером запись value=""
для первой опции, просто убедитесь, что getAsString()
никогда не возвращает null, вместо этого возвратите ""
(пустая строка).
@BalusC
<h:form id="form">
...
<p:selectOneMenu id="targetStep" value="#{action.targetStep}" required="true">
<o:converter converterId="omnifaces.ListIndexConverter" list="#{entity.stepList}" />
<f:selectItems var="step" value="#{entity.stepList}" itemLabel="#{step.name}"
itemValue="#{step}" />
</p:selectOneMenu>
<p:commandButton process="@this" update="@widgetVar(stepDialog)"
oncomplete="PF('stepDialog').show()" icon="#{icons.addStep}"
value="#{bundle.addStep}">
<f:setPropertyActionListener target="#{viewScope.step}"
value="#{s:newInstance('it.shape.edea2.jpa.WorkflowStep')}" />
</p:commandButton>
<p:message for="targetStep" />
...
</h:form>
<p:dialog widgetVar="stepDialog" header="#{bundle.addStep}" modal="true" dynamic="true"
resizable="false">
<h:form>
<p:panelGrid columns="2" styleClass="app-full-width">
<h:outputLabel value="#{bundle.name}" />
<h:panelGroup>
<p:inputText id="name" value="#{step.name}" required="true" />
<p:message for="name" />
</h:panelGroup>
...
<f:facet name="footer">
<p:commandButton process="@form" update="@form :form"
oncomplete="hideDialog('stepDialog', args)" icon="#{icons.confirm}"
value="#{bundle.confirm}">
<p:collector value="#{step}" addTo="#{entity.stepList}" />
<f:setPropertyActionListener target="#{action.targetStep}"
value="#{step}" />
</p:commandButton>
</f:facet>
</p:panelGrid>
</h:form>
</p:dialog>
Ваш omnifaces.ListIndexConverter
на помощь:)
Ответ 4
BalusC (опять же) прибил это для меня.
У меня была та же проблема, и, как ранее указывал BalusC, мой конвертер getAsString() возвращал свойство объекта "firstname".
@Override
public String getAsString (контекст FacesContext, компонент UIComponent, значение Object) {
if (value == null || value.equals("")) {
return "";
}
else {
return String.valueOf(((Employee) value).getfirstname());
}
}
Я изменил это, чтобы вернуть id, и он начал работать как ожидалось.
@Override public String getAsString (контекст FacesContext, компонент UIComponent, значение Object) {
if (value == null || value.equals("")) {
return "";
}
else {
return String.valueOf(((Employee) value).getId());
}
}
BalusC, ваше стремление объяснить теорию чрезвычайно ценится. Ты неистовый!