自定义 jsf ui 组件来替换 <f:selectItems />
custom jsf ui component to replace <f:selectItems />
我一直在尝试为 jsf 创建一个自定义 ui 组件来替换 <f:selectItems />
,它包含在 selectOneMenu 中。所以我的 facesComponent 需要生成所有选项,而 selectOneMenu 提供 <select></select>
.
问题是选项没有呈现在 selectOneMenu 内部,而是呈现在它的外部。
我的 facesComponent 看起来像这样:
@FacesComponent(value = "be.mokuril.jsf.SelectItemsForEnum")
public class SelectItemsForEnum extends UISelectItems {
@Override
public void encodeAll(FacesContext facesContext) throws IOException {
ResponseWriter responseWriter = ResponsefacesContext.getResponseWriter();
responseWriter.startElement("option", null);
responseWriter.writeAttribute("value", 1, null);
responseWriter.write("option1");
responseWriter.endElement("option");
responseWriter.startElement("option", null);
responseWriter.writeAttribute("value", 2, null);
responseWriter.write("option2");
responseWriter.endElement("option");
}
这是我的标签库:
<facelet-taglib xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.0" id="mw"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
>
<namespace>http://www.mokuril.be/jsf/mw</namespace>
<composite-library-name>mw</composite-library-name>
<tag>
<tag-name>selectItemsForEnum</tag-name>
<component>
<component-type>be.mokuril.jsf.SelectItemsForEnum</component-type>
</component>
</tag>
以及重现问题的 xhtml:
<h:form>
<h:selectOneMenu>
<mw:selectItemsForEnum />
</h:selectOneMenu>
</h:form>
我也一直在看组件树:
<HtmlSelectOneMenu disabled="false" id="j_idt7" immediate="false" inView="true" localValueSet="false" readonly="false" rendered="true" required="false" transient="false" valid="true">
<SelectItemsForEnum id="j_idt8" inView="true" rendered="true" transient="false"/>
</HtmlSelectOneMenu>
如果我使用 <f:selectItems />
而不是我的组件,我会得到这个:
<UISelectItems id="j_idt9" inView="true" rendered="true" transient="false"/>
这实际上是我期望的样子,但我显然必须忽略一些重要的事情。
您的具体问题是因为 UISelectOne
/UISelectMany
组件将扫描它们的 direct 子组件以查找 UISelectItem(s)
实例。当你使用复合组件时,它的内容基本上被包装在一个 UIPanel
组件中,它不是 UISelectItem(s)
的实例,所以选择组件将忽略它。从技术上讲,您应该使用自定义组件而不是复合组件。另见 When to use <ui:include>, tag files, composite components and/or custom components?
但是,您会偶然发现下一个问题:UISelectOne
/UISelectMany
将继续自行呈现所有选项并忽略渲染器的输出。基本上,没有一个 <f:xxx>
组件会自己渲染 HTML。此责任由其 <h:xxx>
父级承担。从技术上讲,如果您想操纵 <f:selectItem(s)>
的输出,您应该覆盖 <h:selectOneMenu>
的渲染器。
是unclear which problem you're trying to solve this way, but if I were to do educated guesses, those questions should most probably answer and solve your real problem the correct way: How to use enum values in f:selectItem(s) and/or How to add tooltip to f:selectItems。
我一直在尝试为 jsf 创建一个自定义 ui 组件来替换 <f:selectItems />
,它包含在 selectOneMenu 中。所以我的 facesComponent 需要生成所有选项,而 selectOneMenu 提供 <select></select>
.
问题是选项没有呈现在 selectOneMenu 内部,而是呈现在它的外部。
我的 facesComponent 看起来像这样:
@FacesComponent(value = "be.mokuril.jsf.SelectItemsForEnum")
public class SelectItemsForEnum extends UISelectItems {
@Override
public void encodeAll(FacesContext facesContext) throws IOException {
ResponseWriter responseWriter = ResponsefacesContext.getResponseWriter();
responseWriter.startElement("option", null);
responseWriter.writeAttribute("value", 1, null);
responseWriter.write("option1");
responseWriter.endElement("option");
responseWriter.startElement("option", null);
responseWriter.writeAttribute("value", 2, null);
responseWriter.write("option2");
responseWriter.endElement("option");
}
这是我的标签库:
<facelet-taglib xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.0" id="mw"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
>
<namespace>http://www.mokuril.be/jsf/mw</namespace>
<composite-library-name>mw</composite-library-name>
<tag>
<tag-name>selectItemsForEnum</tag-name>
<component>
<component-type>be.mokuril.jsf.SelectItemsForEnum</component-type>
</component>
</tag>
以及重现问题的 xhtml:
<h:form>
<h:selectOneMenu>
<mw:selectItemsForEnum />
</h:selectOneMenu>
</h:form>
我也一直在看组件树:
<HtmlSelectOneMenu disabled="false" id="j_idt7" immediate="false" inView="true" localValueSet="false" readonly="false" rendered="true" required="false" transient="false" valid="true">
<SelectItemsForEnum id="j_idt8" inView="true" rendered="true" transient="false"/>
</HtmlSelectOneMenu>
如果我使用 <f:selectItems />
而不是我的组件,我会得到这个:
<UISelectItems id="j_idt9" inView="true" rendered="true" transient="false"/>
这实际上是我期望的样子,但我显然必须忽略一些重要的事情。
您的具体问题是因为 UISelectOne
/UISelectMany
组件将扫描它们的 direct 子组件以查找 UISelectItem(s)
实例。当你使用复合组件时,它的内容基本上被包装在一个 UIPanel
组件中,它不是 UISelectItem(s)
的实例,所以选择组件将忽略它。从技术上讲,您应该使用自定义组件而不是复合组件。另见 When to use <ui:include>, tag files, composite components and/or custom components?
但是,您会偶然发现下一个问题:UISelectOne
/UISelectMany
将继续自行呈现所有选项并忽略渲染器的输出。基本上,没有一个 <f:xxx>
组件会自己渲染 HTML。此责任由其 <h:xxx>
父级承担。从技术上讲,如果您想操纵 <f:selectItem(s)>
的输出,您应该覆盖 <h:selectOneMenu>
的渲染器。
是unclear which problem you're trying to solve this way, but if I were to do educated guesses, those questions should most probably answer and solve your real problem the correct way: How to use enum values in f:selectItem(s) and/or How to add tooltip to f:selectItems。