如何在动作侦听器中更新 EditableValueHolder 的值?

How to update value of EditableValueHolder in action listener?

我有这个 JSF(Java EE 7,由 GlassFish 4.1 + PrimeFaces 5.1 提供)表单,其中包含主机名、端口号等数据库连接信息。此表单的一部分是 URL 字段。我希望这个字段是可编辑的,但我也希望能够根据其他字段设置值。

为此,我创建了一个带有动作侦听器的按钮,我在其中读取来自 request parameter map and generate the new URL value. Then I want to put the new value in the URL field and use that value instead of the posted data. What I tried is to get the component as EditableValueHolder and set the submitted value and render the response. I also tried setting the component's value and calling resetValue 的已发布数据。

最好的结果是 URL 字段在单击两次后更新。

XHTML:

<p:inputText id="url"
             size="50"
             value="#{database.url}"/>
<p:commandButton icon="ui-icon-arrowrefresh-1-w"
                 immediate="true"
                 actionListener="#{database.createConnectionURL('namingContainer')}">
  <p:ajax update="url" />
</p:commandButton>

Bean(使用 OmniFaces):

UIComponent urlComponent = Faces.getViewRoot().findComponent(namingContainer + "url");
if (urlComponent instanceof EditableValueHolder) {
  EditableValueHolder editValHolder = (EditableValueHolder) urlComponent;
  editValHolder.setSubmittedValue(urlValue);
}
Faces.getContext().renderResponse();

immediate="true" 是 JSF 1.x 的遗留物,当时无法仅处理一组特定的输入 and/or 按钮。然后它经常被滥用来处理一组特定的输入 and/or 按钮而不是 prioritize validation。当你手头有 JSF2 ajax 时,你最好不要使用它。

使用 JSF2 ajax 你可以只使用 execute="..." 或者在 PrimeFaces 的情况下 process="..." 到 execute/process 只有一组特定的 inputs/buttons.

<p:inputText id="url"
             size="50"
             value="#{database.url}" />
<p:commandButton icon="ui-icon-arrowrefresh-1-w"
                 process="@this"
                 action="#{database.createConnectionURL('namingContainer')}" 
                 update="url" />

然后你可以只更新模型值。

public void createConnectionURL(String namingContainer) {
    // ...
    url = urlValue;
}

请注意,我已将 <p:ajax update> 移回 <p:commandButton>。也许你在混用 <h:commandButton>.

另请参阅:

  • Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes

与具体问题无关,要使用 OmniFaces 处理组件,最好使用 Components 实用程序 class.