为什么选择OneMenu发送ItemLabel到转换器?

时间:2011-08-11 08:31:44

标签: jsf converter

我的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();
}

在此转换器上,Argument'String value'给出itemLabel 我为什么会这样? 我在这个字符串上使用itemValue

4 个答案:

答案 0 :(得分:19)

我不确定为什么你得到了项目标签而不是getAsObject()里面的项目值。也许您的getAsString()做错了,并且根据学生ID返回学生姓名。

无论如何,我可以说你的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请求参数传递。但是,您将学生ID指定为项目值而不是整个学生对象。您需要指定整个学生对象。您还应确保#{studBean.selectedStudent}引用Student属性,而不是代表学生ID的某些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>

和你的转换器如下(省略了零空值检查):

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属性学生证。

答案 1 :(得分:1)

您必须在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方面,你必须填写studentSelectItemList选择项。

private List<SelectItem> studentSelectItemList;

//fill studentSelectItemList at the appropriate place
  studentSelectItemList.add(new SelectItem(studentId,studentName));

完成这些设置后,您应将学生ID作为选择值。

答案 2 :(得分:0)

今天我遇到了同样的问题。

这是由错误的渲染引起的:

<select ...>
    <option>None</option>
    <option value="1">First</option>
    <option value="2">Second</option>
</select>

省略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救援:)

答案 3 :(得分:0)

BalusC(再次)为我钉了这个。 我遇到了同样的问题,正如BalusC先前指出的那样,我的转换器的getAsString()方法返回了我的对象&#34; firstname&#34;属性。

@覆盖 public String getAsString(FacesContext context,UIComponent component,Object value){

    if (value == null || value.equals("")) {
        return "";
    }
    else {
        return String.valueOf(((Employee) value).getfirstname());
    }

}

我改变了这个以返回id,它开始按预期工作。

@覆盖     public String getAsString(FacesContext context,UIComponent component,Object value){

    if (value == null || value.equals("")) {
        return "";
    }
    else {
        return String.valueOf(((Employee) value).getId());
    }

}

BalusC您非常感谢您解释该理论的努力。你是天才!