了解 SelectItemGroup

Understanding SelectItemGroup

深入研究 RadioRenderer 源代码,我注意到以下内容:

方法

@Override
protected void renderOption(FacesContext context,
                            UIComponent component,
                            Converter converter,
                            SelectItem curItem,
                            Object currentSelections,
                            Object[] submittedValues,
                            boolean alignVertical,
                            int itemNumber,
                            OptionComponentInfo optionInfo) throws IOException

RadioRenderer 中覆盖 class 正在从标准 public void encodeEnd(FacesContext context, UIComponent component) 渲染器方法中调用。但是有如下一段代码:

Iterator<SelectItem> items =
          RenderKitUtils.getSelectItems(context, component);
//some code
while (items.hasNext()) {
        SelectItem curItem = items.next();
        idx++;
        // If we come across a group of options, render them as a nested
        // table.
        if (curItem instanceof SelectItemGroup) {
             // do some
        else {
             // do another
        }
}

因此,我通过示例进行了尝试:

<h:selectOneRadio>
    <f:selectItem />
    <f:selectItems value="#{myBean.vals}" />
    <f:selectItems value="#{myBean.valss}" />
</h:selectOneRadio>

以及 selectItemselectItems es 被视为不是 SelectItemGroup 的实例。对于 selectItem 这非常清楚,但我预计 selectItems 会映射到 SelectItemGroup 实例。

你不能稍微澄清一下吗?

不能以声明方式创建。它只能以编程方式创建。 <f:selectItems> 还支持 List<SelectItem>javax.faces.model.SelectItem instances of which the SelectItemGroup is a subclass. Below is an extract of relevance of its javadoc:

SelectItemGroup is a subclass of SelectItem that identifies a set of options that will be made available as a subordinate "submenu" or "options list", depending upon the requirements of the UISelectMany or UISelectOne renderer that is actually used. In general, the value property of this instance will be ignored, and the label property of this instance will be used to label the submenu.

以下是如何创建它们的基本示例:

private List<SelectItem> availableItems; // +getter

@PostConstruct
public void init() {
    availableItems = new ArrayList<>();

    SelectItemGroup group1 = new SelectItemGroup("Group 1");
    group1.setSelectItems(new SelectItem[] {
        new SelectItem("Group 1 Value 1", "Group 1 Label 1"),
        new SelectItem("Group 1 Value 2", "Group 1 Label 2"),
        new SelectItem("Group 1 Value 3", "Group 1 Label 3")
    });
    availableItems.add(group1);

    SelectItemGroup group2 = new SelectItemGroup("Group 2");
    group2.setSelectItems(new SelectItem[] {
        new SelectItem("Group 2 Value 1", "Group 2 Label 1"),
        new SelectItem("Group 2 Value 2", "Group 2 Label 2"),
        new SelectItem("Group 2 Value 3", "Group 2 Label 3")
    });
    availableItems.add(group2);
}
<f:selectItems value="#{bean.availableItems}" />

<h:selectOneRadio> 内,它将呈现为嵌套的 table(恕我直言,这是一个糟糕的呈现,他们最好将组标签呈现为 <thead>,但除此之外).当您将 layout 设置为 pageDirection 时,它最好可见,否则所有内容将显示在一行中 (lineDirection)。

<h:selectOneRadio layout="pageDirection">
    <f:selectItems value="#{bean.availableItems}" />
</h:selectOneRadio>


<h:selectOneMenu> 中,它将呈现为一棵树,选项值嵌套在 <optgroup> 中(这实际上是 SelectItemGroup 的主要用例):

<h:selectOneMenu>
    <f:selectItems value="#{bean.availableItems}" />
</h:selectOneMenu>


<h:selectManyListbox> also supports it (the <h:selectOneListbox>渲染效果完全一样,但只支持单选):

<h:selectManyListbox>
    <f:selectItems value="#{bean.availableItems}" />
</h:selectManyListbox>


<h:selectManyCheckbox> 具有与 <h:selectOneRadio>:

相同的(语义上尴尬的)嵌套 table 呈现
<h:selectManyCheckbox layout="pageDirection">
    <f:selectItems value="#{bean.availableItems}" />
</h:selectManyCheckbox>


<h:selectManyMenu> 一点用处都没有,所以我会跳过它。

另请参阅: