如何在复合组件中参数化 requiredMessage 属性?

发布于 2025-01-05 06:20:10 字数 564 浏览 1 评论 0原文

BalusC 为有关如何为每个复合组件设置消息的问题提供了一个很好的答案。 为不同的复合组件指定不同的错误消息 答案涉及使用每个组件的资源包。

我已经应用了这种方法,但是当我在消息中使用 {0} 来指定当前组件标签作为消息的一部分时,{0} 将按我的方式呈现错误,而不是得到解决。当我使用这种方法时,这种标签分辨率是否可用?或者我是否必须在复合组件中手动构建错误消息?例如,

requiredMessage="#{cc.resourceBundleMap.requiredMessage} #{cc.attrs.prefix} #{cc.attrs.label}"

我想更深层次的问题是如何在资源包中参数化消息字符串?我需要构建某种自定义消息解析器吗?

BalusC provided a good answer to a question about how to set messages per composite component. Specifying different error messages for different composite components
The answer involved using per component resource bundles.

Ive applied this approach but when I use {0} in the message to specify the current component label as part of the message, the {0} is rendered as is in my error, rather than being resolved. Is this resolution of labels available when I use this approach? Or do I have to manually build up the error message in the composite component? e.g.

requiredMessage="#{cc.resourceBundleMap.requiredMessage} #{cc.attrs.prefix} #{cc.attrs.label}"

I guess the deeper question is how can I have parameterised message strings in my resource bundle? Will I need to build some kind of custom message resolver?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

-残月青衣踏尘吟 2025-01-12 06:20:10

不幸的是,requiredMessage(以及validatorMessageconverterMessage)属性默认情况下不可参数化。我认为无论如何这都没有什么意义,因为它们特别依赖于特定的组件。复合组件通常不包含多个相同组件。您需要为每个单独的组件指定单独的消息。

但理论上可以创建自定义 EL 函数 负责消息格式化工作。该方法看起来像这样:

public static String format(String message, Object argument1, Object argument2) {
    return MessageFormat.format(message, argument1, argument2);
}

其使用方式如下:

requiredMessage="#{util:format(cc.resourceBundleMap.requiredMessage, cc.attrs.prefix, cc.attrs.label)}"

唯一的缺点是您无法创建可以接受可变参数的 EL 函数。这是 EL 规范的限制。因此,如果您希望能够传递可变参数,则需要为所需的每个可能数量的参数创建一个单独的 EL 函数和一个 Java 方法。

作为完全不同的替代方案,您可以创建自定义Validator并将其附加到特定的输入组件。您甚至可以将验证器方法直接放入通过 与复合组件关联的“支持组件”中。如果您删除 required 属性,那么将立即调用此验证器,您可以自由地按照自己想要的方式撰写消息。

例如

<h:inputText id="foo" validator="#{cc.validateFoo}" requiredMessage="#{cc.resourceBundleMap.requiredMessage}" />

public void validateFoo(FacesContext context, UIComponent component, Object value) {
    if (value == null || value.toString().trim().isEmpty()) {
        String requiredMessage = (String) component.getAttributes().get("requiredMessage");
        String prefix = (String) getAttributes().get("prefix");
        String label = (String) getAttributes().get("label");
        throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR,
            MessageFormat.format(requiredMessage, prefix, label), null));
    }
}

Unfortunately, the requiredMessage (and validatorMessage and converterMessage) attribues are not parameterizable by default. I think it would make little sense anyway as they are tied to a specific component in particular. A composite component does usually not contain a multiple of the same components. You would need to specify separate messages for every individual component.

It's in theory however possible to create a custom EL function which does the message formatting job. The method would look something like this:

public static String format(String message, Object argument1, Object argument2) {
    return MessageFormat.format(message, argument1, argument2);
}

which is to be used something like this:

requiredMessage="#{util:format(cc.resourceBundleMap.requiredMessage, cc.attrs.prefix, cc.attrs.label)}"

The only disadvantage is that you can't create EL functions which can take varargs. This is a limitation of the EL specification. So if you intend to be able to pass variable arguments, you'd need to create a separate EL function and a Java method for every possible amount of arguments needed.

As a completely different alternative, you could create a custom Validator and attach it to the particular input component. You can even put the validator method straight in the "backing component" which is associated with the composite component by <cc:interface componentType>. If you remove the required attribute, then this validator will immediately be invoked where you've the freedom to compose messages the way you want.

E.g.

<h:inputText id="foo" validator="#{cc.validateFoo}" requiredMessage="#{cc.resourceBundleMap.requiredMessage}" />

with

public void validateFoo(FacesContext context, UIComponent component, Object value) {
    if (value == null || value.toString().trim().isEmpty()) {
        String requiredMessage = (String) component.getAttributes().get("requiredMessage");
        String prefix = (String) getAttributes().get("prefix");
        String label = (String) getAttributes().get("label");
        throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR,
            MessageFormat.format(requiredMessage, prefix, label), null));
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文