小编典典

了解 PrimeFaces 进程/更新和 JSF f:ajax 执行/渲染属性

all

PrimeFaces组件和标签中的processand到底是什么?update``p:commandXxx``execute``render``f:ajax

验证时哪个有效?属性做什么update而不是从后端更新组件的值?属性是否process将值绑定到模型?@this,
@parent,@all@form这两个属性到底是做什么的?

下面的示例运行良好,但我对基本概念有点困惑。

<p:commandButton process="@parent"
                 update="@form"
                 action="#{bean.submit}" 
                 value="Submit" />

阅读 56

收藏
2022-06-21

共1个答案

小编典典

<p:commandXxx process> <p:ajax process> <f:ajax execute>

process属性是服务器端的,只能影响UIComponent实现EditableValueHolder(输入字段)或ActionSource(命令字段)。该process属性使用空格分隔的客户端
ID 列表告诉 JSF,在(部分)表单提交时,哪些组件必须在整个 JSF 生命周期中准确处理。

然后 JSF 将应用请求值(根据组件自己的客户端 ID 查找 HTTP
请求参数,然后在组件的情况下将其设置为提交的值,或者在组件的情况下将其设置为新的EditableValueHolder队列),执行转换、验证和更新模型值(仅组件),最后调用队列(仅组件)。JSF
将跳过属性未涵盖的所有其他组件的处理。此外,在应用请求值阶段其属性评估为的组件也将被跳过,作为防止篡改请求的一部分。ActionEventActionSource``EditableValueHolder``ActionEvent``ActionSource``process``rendered``false

请注意,在ActionSource组件(例如<p:commandButton>)的情况下,将组件本身包含在process属性中非常重要,尤其是在您打算调用与组件关联的操作时。因此,下面的示例打算在调用某个命令组件时仅处理某些输入组件是行不通的:

<p:inputText id="foo" value="#{bean.foo}" />
<p:commandButton process="foo" action="#{bean.action}" />

它* 只会处理#{bean.foo}而不处理. 您还需要包含命令组件本身: *#{bean.action}

<p:inputText id="foo" value="#{bean.foo}" />
<p:commandButton process="@this foo" action="#{bean.action}" />

或者,正如您显然发现的那样,使用@parentif 它们恰好是唯一具有共同父级的组件:

<p:panel><!-- Type doesn't matter, as long as it's a common parent. -->
    <p:inputText id="foo" value="#{bean.foo}" />
    <p:commandButton process="@parent" action="#{bean.action}" />
</p:panel>

或者,如果它们都恰好是父UIForm组件的唯一组件,那么您也可以使用@form

<h:form>
    <p:inputText id="foo" value="#{bean.foo}" />
    <p:commandButton process="@form" action="#{bean.action}" />
</h:form>

如果表单包含更多您想在处理中跳过的输入组件,这有时是不可取的,在您想根据一个 ajax 监听器方法。您不希望其他输入组件上的验证错误阻止执行 ajax
侦听器方法。

然后是@all. 这在属性上没有特殊效果process,只是在update属性上。A 的process="@all"行为与
完全相同process="@form"。无论如何,HTML 不支持一次提交多个表单。

@none顺便说一句,如果您绝对不需要处理任何内容,但 只想 通过
更新某些特定部分update,特别是那些内容不依赖于提交的值或动作侦听器的部分,那么还有一个可能很有用。

需要注意的是,该process属性对 HTTP 请求负载(请求参数的数量) 没有影响。 这意味着,发送包含在 HTML
表示中的“所有内容”的默认 HTML 行为<h:form>不会受到影响。如果您的表单很大,并且希望将 HTTP
请求负载减少到处理中绝对必要的那些,即只有这些被process属性覆盖,那么您可以partialSubmit在 PrimeFaces Ajax
组件中将属性设置为 in<p:commandXxx ... partialSubmit="true"><p:ajax ... partialSubmit="true">。您还可以通过编辑web.xml和添加来配置此“全局”

<context-param>
    <param-name>primefaces.SUBMIT</param-name>
    <param-value>partial</param-value>
</context-param>

或者,您也可以使用<o:form>默认为该行为的
OmniFaces 3.0+。

与 PrimeFaces 特定等效的标准processJSFexecute来自<f:ajax execute>.
它的行为完全相同,只是它不支持逗号分隔的字符串,而 PrimeFaces
支持(尽管我个人建议只坚持空格分隔的约定),也不支持@parent关键字。此外,知道<p:commandXxx process>默认为@formwhile<p:ajax process><f:ajax execute>默认为@this.
最后,了解process支持所谓的“PrimeFaces 选择器”也很有用,


<p:commandXxx update> <p:ajax update> <f:ajax render>

update属性是客户端的,可以影响所有UIComponents 的 HTML 表示。该update属性使用以空格分隔的客户端 ID 列表告诉
JavaScript(负责处理 ajax 请求/响应的部分),HTML DOM 树中的哪些部分需要更新为对表单提交的响应。

然后 JSF 将为此准备正确的 ajax 响应,其中 包含要更新的请求部分。updateJSF 将跳过ajax
响应中属性未涵盖的所有其他组件,从而使响应负载保持较小。此外,在渲染响应阶段其rendered属性评估为的组件将被跳过。false请注意,即使它会返回true,JavaScript
也无法在 HTML DOM 树中更新它(如果它最初是)false。您需要将其包装或更新其父级。另请参阅Ajax
更新/渲染不适用于已渲染属性的组件

通常,您 只想在(部分)表单提交时更新 真正 需要在客户端“刷新”的组件。下面的示例通过以下方式更新整个父表单@form

<h:form>
    <p:inputText id="foo" value="#{bean.foo}" required="true" />
    <p:message id="foo_m" for="foo" />
    <p:inputText id="bar" value="#{bean.bar}" required="true" />
    <p:message id="bar_m" for="bar" />
    <p:commandButton action="#{bean.action}" update="@form" />
</h:form>

(请注意,process属性被省略,因为它默认为@form已经)

虽然这可能工作正常,但在这个特定示例中,输入和命令组件的更新是不必要的。除非您更改模型值foobar内部action方法(从 UX
角度来看,这反过来又不直观),否则没有必要更新它们。消息组件是唯一 真正 需要更新的组件:

<h:form>
    <p:inputText id="foo" value="#{bean.foo}" required="true" />
    <p:message id="foo_m" for="foo" />
    <p:inputText id="bar" value="#{bean.bar}" required="true" />
    <p:message id="bar_m" for="bar" />
    <p:commandButton action="#{bean.action}" update="foo_m bar_m" />
</h:form>

然而,当你有很多时,这会变得乏味。这就是 PrimeFaces 选择器存在的原因之一。这些消息组件在生成的 HTML 输出中有一个通用的样式类ui- message,因此也应该执行以下操作:

<h:form>
    <p:inputText id="foo" value="#{bean.foo}" required="true" />
    <p:message id="foo_m" for="foo" />
    <p:inputText id="bar" value="#{bean.bar}" required="true" />
    <p:message id="bar_m" for="bar" />
    <p:commandButton action="#{bean.action}" update="@(.ui-message)" />
</h:form>

(请注意,您应该保留消息组件上的 ID,否则@(...)将无法正常工作!再次,请参阅PrimeFaces 选择器如何在
update=”@(.myClass)” 中工作?
了解详细信息)

@parent仅更新父组件,从而覆盖当前组件和所有兄弟姐妹及其子组件。如果您将表单分成不同的组并各自负责,这将更加有用。显然,@this更新只是当前组件。通常,只有当您需要在
action 方法中更改组件自己的 HTML 属性之一时,才需要这样做。例如

<p:commandButton action="#{bean.action}" update="@this" 
    oncomplete="doSomething('#{bean.value}')" />

想象一下,在中更改了oncomplete使用的需求,那么如果组件没有更新,那么这个构造就不会起作用,原因很简单,它是生成的 HTML
输出的一部分(因此那里的所有 EL 表达式都被评估在渲染响应期间)。value``action``oncomplete

更新整个@all文档,应该小心使用。通常,您希望对此使用真正的 GET 请求,而不是通过普通链接 ( <a>or )
或通过or<h:link>的重定向后POST 。在效果上,与非 ajax(非部分)提交的效果完全相同。在我的整个 JSF
职业生涯中,我遇到的唯一明智的用例是完整地显示错误页面,以防在 ajax 请求期间发生异常。

与 PrimeFaces 特定等效的标准updateJSFrender来自<f:ajax render>.
它的行为完全相同,只是它不支持逗号分隔的字符串,而 PrimeFaces
支持(尽管我个人建议只坚持空格分隔的约定),也不支持@parent关键字。两者updaterender默认为@none(即“无”)。


2022-06-21