JSF 自定义组件中的更新属性需要完整的元素 ID 路径,而直接 PrimeFaces 组件使用短元素 ID 路径运行

Update attribute in JSF custom component expect full element ID path where as direct PrimeFaces component runs with short element ID path

我正在使用带有更新属性的 <p:commandButton> 标签,并将更新属性中的当前元素 ID 作为 currentForm: messages 传递。类似于:update="currentForm: messages"。其中 messages 是 <div> 元素的 id,我想在请求调用后更新它。

这工作正常。

现在,我使用与主模板中相同的命令按钮创建了一个复合组件,并将 PrimeFaces 命令按钮替换为创建的自定义命令按钮。 (目前没有在创建的命令按钮中进行任何自定义更改,只是在这个命令按钮中使用 prime faces 命令按钮)

当我呈现模板时,它向我抱怨 ID 给定的更新属性错误,如下所示:

javax.faces.FacesException: Cannot find component with expression "currentForm

如果我为该元素提供完整的元素 ID 路径,它将再次起作用。

虽然如果我们提供元素的完整元素 ID 路径很好,但令我惊讶的是为什么当我直接调用 PrimeFaces 命令按钮时它会起作用?

那是因为复合组件像<h:form><h:dataTable>等也是命名容器。它们对 ajax 客户端 ID 的影响在以下相关问题中有所概述:How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar".

这样做是因为在同一个命名容器父级中多次重复使用复合组件时,您 运行 会在复合组件的实现上出现 "duplicate component ID" 错误。另请参阅此相关问题:Should a composite component really require namingcontainer interface?

如果您绝对肯定复合组件是满足具体需求的正确解决方案,因此不是标记文件(许多初学者由于其零配置性质而过度使用复合组件,while it should really best only be used if you intend to bind a single model property to a bunch of closely related components ),那么您可以考虑以下替代方法来更新消息组件:

  1. 要么动态传递目标客户端ID:

    <my:compositeButton ... update=":#{messages.clientId}" />
    ...
    <p:messages binding="#{messages}" ... />
    

    (注:the code is as is; you don't need to bind it to a bean property or so!

  2. 或者让 PrimeFaces 在每次 ajax 请求时自动更新消息组件:

    <my:compositeButton ... />
    ...
    <p:messages autoUpdate="true" ... />