JSF 2.2 多 Select 自定义组件

JSF 2.2 Multi Select Custom Component

为了支持我们组织的组件库,我想创建一个增强的 selectManyMenu。一个要求是它类似于具有下拉菜单的类型,其菜单项具有显示它们是否被 selected 的复选框。最重要的是,我想要下拉菜单的第一行,由于缺少更好的术语而始终可见显示 'bubbles' 的区域,其中包含 selected 项目的标签还有一个 'X' 按钮来删除每一个,类似于 'tag' 小部件。

我想创建一个 JSF 自定义组件,而不是用一些 jQuery 插件来装饰现有的 <h:selectManyMenu> ] 我不知道它是如何工作的。老实说,我发现 none 非常适合我们的 UI,而且从根本上说,我不觉得这是对 JSF 的良好使用,所以在一些 jQuery 当 JSF 具有如此强大的自定义组件功能时的小部件。

为了解决我当前的问题,我设置了一个自定义组件 class,它扩展 UIInput 并提供 encode*() 方法来呈现 <select> 及其<option> 标签与 <h:selectManyMenu> 相同。 decode() 方法有问题:

@Override
public void decode(FacesContext context) {
    Map<String, String> requestParams = context.getExternalContext().getRequestParameterMap();
    String clientId = getClientId();
    Object param = requestParams.get(clientId);
    LOG.debug("param: {}", param);
}

问题是 param 无论我 select 有多少项,最终都是一个字符串。我已经在前端验证了当我使用 <h:selectManyMenu> 时发送的完全相同的 POST 请求,所以我猜我必须在 decode() 中对来自请求。

对于奖励积分,任何人都可以指出一些源代码的简明解释,比如 <h:inputText>。我能够浏览我们正在使用的 JSF 实现的源代码,Mojarra,但它变得非常难以理解,因为它使用单独的渲染器,以及各种工厂和 select 使用哪个渲染器等。到目前为止,我一直依靠复合组件,在必要时使用支持组件,但是我认为这个和其他一些正在准备中的组件超出了复合组件可以有效使用的范围。

此外,这是实现我所追求目标的最佳方法吗?为现有 <h:selectManyMenu> 创建一个自定义渲染器会更好吗?这似乎是一个更优雅的解决方案,因为这个组件基本上是一个 selectManyMenu 只是渲染有点不同并且在前端有一点 javascript。

我想你的问题可以归结为:

How can I obtain a request parameter with multiple values in JSF?

答案是:使用ExternalContext#getRequestParameterValuesMap().

@Override
public void decode(FacesContext context) {
    Map<String, String[]> requestParamValues = context.getExternalContext().getRequestParameterValuesMap();
    String clientId = getClientId(context);
    String[] params = requestParamValues.get(clientId);
    // ...
}

but it gets extremely hard to follow since it uses separate renderers, and all sorts of factories and things to select which renderer to use, etc

不确定,但也许您正在寻找 What is the relationship between component family, component type and renderer type? or How do I determine the renderer of a built-in component

Would I be better off creating a custom renderer for the existing <h:selectManyMenu>? That seems like an even more elegant solution since this component basically IS a selectManyMenu just rendered a little differently and having a bit of javascript on the front end.

确实更有意义。