Understanding SelectItemGroup

Deadly 提交于 2019-12-07 23:27:44

问题


Digging into the RadioRenderer source code I've noticed the following thing:

The method

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

overriden in the RadioRenderer class is being called from the standard public void encodeEnd(FacesContext context, UIComponent component) Renderer method. But there was the following piece of code:

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
        }
}

So, I tried it by the example:

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

and the selectItem and the selectItemses were treated as not the instances of the SelectItemGroup. For selectItem that's perfectly clear, but I expected that selectItems would be mapped to the SelectItemGroup instance.

Couldn't you clarify the thing a bit?


回答1:


It can not declaratively be created. It can only programmatically be created. The <f:selectItems> also supports List<SelectItem> with 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.

Here's a basic example of how you can create them:

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}" />

Inside <h:selectOneRadio> it will render as a nested table (which is IMHO a poor rendering, they'd better have rendered the group label as a <thead>, but that aside). It's best visible when you set layout to pageDirection, otherwise everything will appear in a single line (lineDirection).

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


And inside the <h:selectOneMenu> it will render as a tree with option values nested in <optgroup> (which is actually the primary use case for SelectItemGroup):

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


The <h:selectManyListbox> also supports it (the <h:selectOneListbox> has exactly the same rendering, but supports only a single selection):

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


The <h:selectManyCheckbox> has the same (semantically awkward) nested table rendering as <h:selectOneRadio>:

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


The <h:selectManyMenu> isn't useful at all, so I'll skip it.

See also:

  • Our selectOneMenu wiki page


来源:https://stackoverflow.com/questions/31905878/understanding-selectitemgroup

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!