JSF 1.2 空 <h:selectManyListbox /> 验证问题

JSF 1.2 empty <h:selectManyListbox /> validation issue

我是 JSF 的新手,我很难理解 JSF 在验证失败后在表单中呈现的值。我正在使用 WebSphere 7 及其默认的 JSF 实现,MyFaces(我认为是 2.0)。

我的 xhtml 如下所示:

<h:form id="form">
    <h:inputText id="text" value="#{backing.text}" required="true"/>
    <h:message for="text" />

    <h:selectManyListbox id="options" value="#{backing.options}" required="true">
        <f:selectItem itemLabel="1" itemValue="1" />
        <f:selectItem itemLabel="2" itemValue="2" />
        <f:selectItem itemLabel="3" itemValue="3" />
    </h:selectManyListbox>
    <h:message for="options" />

    <h:commandButton value="Save" />
</h:form>

我的支持 bean 是这样的:

public class Backing {

    private String text;

    private String[] options;

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public String[] getOptions() {
        return options;
    }

    public void setOptions(String[] options) {
        this.options = options;
    }
}
  1. 我用一些文字填充 <h:inputText />
  2. 我select两个选项<h:selectManyListbox />
  3. 我按下 'Save' 按钮
  4. 表单使用我为 <h:inputText /> 输入的值和我在 <h:selectManyListbox /> 上 select 编辑的选项呈现(没有显示验证消息,正如预期的那样)
  5. 现在...
  6. 我清空了<h:inputText />
  7. 我deselect两个选项来自<h:selectManyListbox />
  8. 我按下 'Save' 按钮
  9. 表单呈现 <h:inputText /> 空,<h:selectManyListbox /> 带有我之前 selected 的选项(如预期的那样显示了两个验证消息)

如您所见,渲染 <h:inputText /><h:selectManyListbox /> 时的行为不同:

我一直在尝试渲染 <h:selectManyListbox /> 没有任何选项 selected 没有破解或弄乱我的代码,但没有运气。

¿这是什么错误吗? ¿我错过了什么吗?

我发现的不太老套的解决方案是复制并重新实现方法 renderOption,覆盖默认 MenuRenderer

原始来源是这样的,因为我不得不反编译(版本 1.2_13)。 请注意,我只粘贴了实际需要更改的行。如果您需要使用此解决方案,则必须复制方法的全部内容:

public class MenuRenderer extends HtmlBasicInputRenderer {
    protected void renderOption(FacesContext context, UIComponent component, Converter converter, SelectItem curItem, Object currentSelections, Object[] submittedValues, HtmlBasicRenderer.OptionComponentInfo optionInfo) throws IOException {
        (...)
        Object valuesArray;
        Object itemValue;
        if (submittedValues != null) {
            boolean containsValue = containsaValue(submittedValues);
            if (containsValue) {
                valuesArray = submittedValues;
                itemValue = valueString;
            } else {
                valuesArray = currentSelections;
                itemValue = curItem.getValue();
            }
        } else {
            valuesArray = currentSelections;
            itemValue = curItem.getValue();
        }
        (...)
    }
}

我这样创建 CustomListboxRendererListboxRenderer 扩展 MenuRenderer):

public class CustomListboxRenderer extends ListboxRenderer {
    @Override
    protected void renderOption(FacesContext context, UIComponent component, Converter converter, SelectItem curItem, Object currentSelections, Object[] submittedValues, HtmlBasicRenderer.OptionComponentInfo optionInfo) throws IOException {
        (...)
        Object valuesArray;
        Object itemValue;
        if (submittedValues != null) {
            valuesArray = submittedValues;
            itemValue = valueString;
        } else {
            valuesArray = currentSelections;
            itemValue = curItem.getValue();
        }
        (...)
    }
}

然后在 faces-config 中添加下一行:

<render-kit>
    <renderer>
        <component-family>javax.faces.SelectMany</component-family>
        <renderer-type>javax.faces.Listbox</renderer-type>
        <renderer-class>CustomListboxRenderer</renderer-class>
    </renderer>
</render-kit>