<p:commandXxx process><p:ajax process><f:ajax execute>
process 属性是服务器端的,只能影响实现EditableValueHolder(输入字段)或ActionSource(命令字段)的UIComponents。 process 属性使用空格分隔的客户端 ID 列表告诉 JSF,在(部分)表单提交时,哪些组件必须在整个 JSF 生命周期中准确处理。
JSF 然后将应用请求值(根据组件自己的客户端 ID 查找 HTTP 请求参数,然后在 EditableValueHolder 组件的情况下将其设置为提交的值,或者在 ActionSource 组件的情况下将新的ActionEvent 排队),执行转换、验证和更新模型值(仅限EditableValueHolder 组件),最后调用排队的ActionEvent(仅限ActionSource 组件)。 JSF 将跳过对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}" />
或者,正如您显然发现的那样,如果它们恰好是唯一具有共同父级的组件,则使用 @parent:
<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>
如果表单包含更多您想在处理过程中跳过的输入组件,这有时是不可取的,这在您想根据当前更新另一个输入组件或某些 UI 部分的情况下更常见ajax 侦听器方法中的输入组件。您不希望其他输入组件上的验证错误阻止执行 ajax 侦听器方法。
然后是@all。这在process 属性中没有特殊效果,而仅在update 属性中。 process="@all" 的行为与 process="@form" 完全相同。 HTML 无论如何都不支持同时提交多个表单。
顺便说一句,还有一个@none,如果您绝对不需要处理任何东西,但仅想通过update更新某些特定部分,特别是那些其内容不依赖于提交的值或操作侦听器的部分。
需要注意的是process 属性对HTTP 请求负载(请求参数的数量)有没有影响。这意味着,发送包含在<h:form> 的 HTML 表示中的“所有内容”的默认 HTML 行为将不受影响。如果您的表单很大,并且希望将 HTTP 请求负载减少到处理中绝对必要的那些,即只有 process 属性覆盖的那些,那么您可以在 PrimeFaces Ajax 组件中设置 partialSubmit 属性,如 @ 987654376@ 或<p:ajax ... partialSubmit="true">。您还可以通过编辑web.xml 并添加来“全局”配置此设置
<context-param>
<param-name>primefaces.SUBMIT</param-name>
<param-value>partial</param-value>
</context-param>
或者,您也可以使用 OmniFaces 3.0+ 的 <o:form>,它默认为这种行为。
等效于 PrimeFaces 特定 process 的标准 JSF 是来自 <f:ajax execute> 的 execute。它的行为完全相同,只是它不支持逗号分隔的字符串,而 PrimeFaces 支持(尽管我个人建议只坚持空格分隔的约定),也不支持 @parent 关键字。此外,知道<p:commandXxx process> 默认为@form 而<p:ajax process> 和<f:ajax execute> 默认为@this 可能很有用。最后,知道process 支持所谓的“PrimeFaces 选择器”也很有用,另见How do PrimeFaces Selectors as in update="@(.myClass)" work?
<p:commandXxx update><p:ajax update><f:ajax render>
update 属性是客户端,可以影响所有UIComponents 的HTML 表示。 update 属性告诉 JavaScript(负责处理 ajax 请求/响应的),使用空格分隔的客户端 ID 列表,HTML DOM 树中的哪些部分需要更新为对表单提交的响应。
JSF 然后会为此准备正确的 ajax 响应,其中包含 仅 请求更新的部分。 JSF 将跳过 ajax 响应中 update 属性未涵盖的所有其他组件,从而使响应负载保持较小。此外,在渲染响应阶段其rendered 属性评估为false 的组件将被跳过。请注意,即使它会返回 true,如果它最初是 false,JavaScript 也无法在 HTML DOM 树中更新它。您需要将其包装或更新其父级。另见Ajax update/render does not work on a component which has rendered attribute。
通常,您希望仅更新真正需要在(部分)表单提交时在客户端“刷新”的组件。下面的例子通过@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)
虽然这可能工作正常,但在这个特定示例中,输入和命令组件的更新是不必要的。除非您在 action 方法中更改模型值 foo 和 bar(这反过来在 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,否则 @(...) 将不起作用!再次,请参阅 How do PrimeFaces Selectors as in update="@(.myClass)" work? 了解详细信息)
@parent 仅更新父组件,从而覆盖当前组件以及所有兄弟姐妹及其子组件。如果您将表单分成不同的组并各自负责,这将更加有用。 @this 显然只更新当前组件。通常,只有当您需要在 action 方法中更改组件自己的 HTML 属性之一时,才需要这样做。例如
<p:commandButton action="#{bean.action}" update="@this"
oncomplete="doSomething('#{bean.value}')" />
假设oncomplete 需要与value 一起使用,而action 中已更改,那么如果不更新组件,则此构造将无法工作,原因很简单,oncomplete 是生成的 HTML 输出的一部分(因此其中的所有 EL 表达式都会在呈现响应期间进行评估)。
@all 更新整个文档,应谨慎使用。通常,您希望通过纯链接(<a> 或<h:link>)或?faces-redirect=true 或ExternalContext#redirect() 的redirect-after-POST 对此使用真正的GET 请求。在效果上,process="@form" update="@all" 与非 ajax(非部分)提交的效果完全相同。在我的整个 JSF 职业生涯中,我遇到的关于 @all 的唯一合理用例是在 ajax 请求期间发生异常时完整显示错误页面。另见What is the correct way to deal with JSF 2.0 exceptions for AJAXified components?
等效于 PrimeFaces 特定 update 的标准 JSF 是来自 <f:ajax render> 的 render。它的行为完全相同,只是它不支持逗号分隔的字符串,而 PrimeFaces 则支持(尽管我个人建议坚持使用空格分隔的约定),也不支持 @parent 关键字。 update 和 render 都默认为 @none(即“无”)。
另请参阅: