Почему 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, ваше стремление объяснить теорию чрезвычайно ценится. Ты неистовый!