Jsf 如何扩展UISelectOne组件for enum属性以自动将所有枚举值填充为选择项?
我想使用简化的selectone标记,它会自动为枚举生成selectitems列表。因此,结果将是:Jsf 如何扩展UISelectOne组件for enum属性以自动将所有枚举值填充为选择项?,jsf,jsf-2,selectonemenu,custom-tag,Jsf,Jsf 2,Selectonemenu,Custom Tag,我想使用简化的selectone标记,它会自动为枚举生成selectitems列表。因此,结果将是: <s:enumSelectOneMenu value="#{myBean.enumValue}"/> 因此,在组件内部,我可以使用反射获取枚举类型和所有枚举值。因此,基本上我需要覆盖来自UiSelectOne的唯一一个方法validateValue(..),并将UiSelectItems列表作为子项放在那里(与Tomahawk中的方法相同,请参见SelectOneLanguag
<s:enumSelectOneMenu value="#{myBean.enumValue}"/>
因此,在组件内部,我可以使用反射获取枚举类型和所有枚举值。因此,基本上我需要覆盖来自UiSelectOne的唯一一个方法validateValue(..),并将UiSelectItems列表作为子项放在那里(与Tomahawk中的方法相同,请参见SelectOneLanguage组件)
但还应该做些什么呢?我需要在我自己的taglib.xml中描述标记属性,但是jsf-impl.jar不包含FaceletsXML-only标记库文件,所以我不能简单地从那里复制所有内容。另外,如果我在taglib.xml中静态地描述标记,我将不得不在每个新版本的JSF上手动更新它,这一点都不好。那么,在JSF中扩展组件并避免大量手动复制粘贴工作的最佳方法是什么
另外,我使用的是JSF2.0,但复合facelets方式不适合我,因为它会产生很多问题,因为复合元素是由NamingContainer组件包装的。所以我只需要“老派”的方式来创建自定义组件
谢谢。扩展一些JSF组件并在不丢失属性的情况下添加行为的最佳(但不是最简单)方法之一是使用PrimeFaces JSF插件。有关它的一些信息,请参见:。虽然它有一些硬编码的值(facelets taglib的名称和输出目录的方式,生成的taglib放在哪里),并且可以在本地更改和重建
这里是pfjsf插件的示例
<!-- Primefaces maven plugin -->
<plugin>
<groupId>org.primefaces</groupId>
<artifactId>maven-jsf-plugin</artifactId>
<version>1.2.1-SNAPSHOT</version>
<executions>
<execution>
<id>generate-ui</id>
<phase>generate-sources</phase>
<configuration>
<uri>http://www.mycompany.com/tags</uri>
<name>rstk-tag</name>
<jsfVersion>2</jsfVersion>
<templatesDir>src/main/java-templates</templatesDir>
<componentConfigsDir>src/main/resources-maven-jsf/ui</componentConfigsDir>
<!-- <standardFacesConfig>src/main/resources-maven-jsf/standard-faces-config.xml</standardFacesConfig> -->
<!-- These are new attributes added manually to plugin source code! -->
<standardFaceletsTaglib>src/main/resources-maven-jsf/standard-facelets-taglib.xml</standardFaceletsTaglib>
<faceletsOutputDirectory>target/generated-sources/maven-jsf-plugin/META-INF</faceletsOutputDirectory>
</configuration>
<goals>
<goal>generate-components</goal>
<goal>generate-facelets-taglib</goal>
</goals>
</execution>
</executions>
</plugin>
然后,该组件可以用作简单的JSF选择一个组件(具有所有标准属性),但不要求每次添加选择项,并允许将任何其他子项放置在该组件上:
<s:enumSelectOneMenu value="#{polis.osMatrixType}" id="registryType">
<p:ajax listener="#{osagoPolisBean.rollOsagoEndDate}" update="osagoUsagePeriod" process="osagoTable" event="change"/>
</s:enumSelectOneMenu>
有什么问题吗?JSF有一个内置的枚举转换器。或者您想避免每次都指定
吗?好的,最好是:
或
?Upd:正确,我需要避开所有selectItems
staffI,看看你在说什么。这其实是个好主意。从理论上讲,一个简单的复合组件和一个支持组件应该可以工作,但我宁愿先自己试验一下,看看它是否真的能像我想象的那样工作。如果我有时间,我会发布一个答案,并确认它确实是这样工作的。我与composite的斗争太久了,试图替换那里的p:列(只是以与上面相同的方式扩展)。最后,我又回到了基本的1.2 facelets块,它工作起来很有魅力,因为它不需要任何uinamingContainer,尽管我失去了继承,不得不在我的taglib.xml中复制许多属性。出于上述目的,我可以再次尝试复合元素,但我不希望在我的应用程序中有两个标记库名称空间!很难记住哪个库(自定义库或复合库)包含标记。很抱歉收到了很多信:(
public class EnumSelectOneMenu extends HtmlSelectOneMenu {
... // Generated staff here
public boolean getRendersChildren() {
return true;
}
/**
* @see javax.faces.component.UIComponentBase#encodeBegin(javax.faces.context.FacesContext)
*/
@Override
public void encodeBegin(FacesContext context) throws IOException {
super.encodeBegin(context);
if (context.isPostback()) {
return;
}
UISelectItems selectItems = new UISelectItems();
try {
selectItems.setValue(getEnumValuesList());
} catch (Exception e) {
log.error("Failed to create enum list", e);
}
getChildren().add(selectItems);
}
/**
* Creates the list of select items of format [ENUM, enum.getDisplay()]
* @return
*/
private List getEnumValuesList() {
List result = new ArrayList();
ValueExpression ve = getValueExpression("value");
Class enumClass = ve.getType(getFacesContext().getELContext());
Method method = ReflectionUtils.findMethod(enumClass, "getDisplay", null);
for (Object e : ve.getType(getFacesContext().getELContext()).getEnumConstants()) {
result.add(new SelectItem(e, (String) ReflectionUtils.invokeMethod(method, e)));
}
return result;
}
}
<s:enumSelectOneMenu value="#{polis.osMatrixType}" id="registryType">
<p:ajax listener="#{osagoPolisBean.rollOsagoEndDate}" update="osagoUsagePeriod" process="osagoTable" event="change"/>
</s:enumSelectOneMenu>