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

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

提问人:Shardendu 提问时间:8/16/2014 最后编辑:Jasper de VriesShardendu 更新时间:11/24/2022 访问量:309466

问:

PrimeFaces 组件和标签中到底是什么?processupdatep:commandXxxexecuterenderf:ajax

哪些在验证时有效?属性的作用是什么,而不是从后端更新组件的值?属性是否将值绑定到模型?、 和 在这两个属性中究竟做了什么?updateprocess@this@parent@all@form

下面的例子工作正常,但我对基本概念有点困惑。

<p:commandButton process="@parent"
                 update="@form"
                 action="#{bean.submit}" 
                 value="Submit" />
JSF PrimeFaces 流程 更新

评论


答:

30赞 faissalb 8/16/2014 #1

通过进程(在 JSF 规范中称为 execute),您告诉 JSF 将处理限制为指定的组件,其他所有内容都被忽略。

update 指示当服务器响应您的请求时将更新哪个元素。

@all : 每个组件都经过处理/渲染。

@this:处理/渲染具有 execute 属性的请求组件。

@form :处理/呈现包含请求组件的表单。

@parent:处理/呈现包含请求组件的父组件。

使用 Primefaces,您甚至可以使用 JQuery 选择器,请查看此博客:http://blog.primefaces.org/?p=1867

349赞 BalusC 8/17/2014 #2

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

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

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

请注意,对于组件(例如),在属性中也包含组件本身非常重要,尤其是在您打算调用与组件关联的操作时。因此,以下示例打算在调用某个命令组件时仅处理某些输入组件,该示例将不起作用: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>

如果表单包含更多您希望在处理中跳过的输入组件,则有时是不可取的,这通常是您想要根据 ajax 侦听器方法中的当前输入组件更新另一个输入组件或某些 UI 部分的情况。也就是说,您不希望其他输入组件上的验证错误阻止执行 ajax 侦听器方法。

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

顺便说一句,如果您绝对不需要处理任何内容,而只想通过更新某些特定部分,尤其是那些内容不依赖于提交的值或操作侦听器的部分,它也可能很有用。@noneupdate

请注意,该属性对 HTTP 请求有效负载(请求参数的数量)没有影响。这意味着,发送包含在 HTML 表示中的“所有内容”的默认 HTML 行为将不受影响。如果您有一个大型表单,并且希望将HTTP请求有效负载减少到处理中绝对必要的这些,即仅这些被属性覆盖,那么您可以在PrimeFaces Ajax组件中将属性设置为或。您还可以通过编辑和添加来“全局”配置此内容process<h:form>processpartialSubmit<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>

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

与特定于 PrimeFaces 的标准 JSF 等效于 。它的行为完全相同,只是它不支持逗号分隔的字符串,而 PrimeFaces 则支持(尽管我个人建议只坚持空格分隔的约定),也不支持关键字。此外,知道默认为 while 和默认为 .最后,了解支持所谓的“PrimeFaces 选择器”也很有用,另请参阅 update=“@(.myClass)” 中的 PrimeFaces 选择器如何工作?processexecute<f:ajax execute>@parent<p:commandXxx process>@form<p:ajax process><f:ajax execute>@thisprocess


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

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

然后,JSF 将为此准备正确的 ajax 响应,包含请求更新的部分。JSF 将跳过 ajax 响应中属性未涵盖的所有其他组件,从而保持响应有效负载较小。此外,在渲染响应阶段,其属性的计算结果将被跳过。请注意,即使它会返回 ,如果 JavaScript 最初是 ,则无法在 HTML DOM 树中更新它。您需要包装它或更新其父级。另请参阅 Ajax update/render does not work on a component which have render attribute.updaterenderedfalsetruefalse

通常,您只想在提交(部分)表单时更新真正需要在客户端“刷新”的组件。下面的示例通过以下方式更新整个父窗体:@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

虽然这可能工作正常,但在此特定示例中,输入和命令组件的更新是不必要的。除非你改变模型值和内部方法(这在用户体验的角度来看是不直观的),否则更新它们就没有意义了。消息组件是唯一真正需要更新的组件:foobaraction

<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 保留在消息组件上,否则 @(...) 将不起作用!同样,请参阅update=“@(.myClass)”中的PrimeFaces选择器如何工作?

仅更新父组件,从而涵盖当前组件以及所有同级组件及其子组件。如果您已将表单分成合理的组,每个组都有自己的责任,这将更有用。显然,更新只是当前组件。通常,仅当您需要在操作方法中更改组件自己的 HTML 属性之一时,才需要这样做。F.D.(英语:F.D.)@parent@this

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

想象一下,需要处理 中更改的组件,那么如果组件没有更新,则此构造将不起作用,原因很简单,这是生成的 HTML 输出的一部分(因此其中的所有 EL 表达式都会在渲染响应期间进行评估)。oncompletevalueactiononcomplete

将更新整个文档,应谨慎使用。通常,您希望通过普通链接 ( 或 ) 或 的 POST 后重定向来代替真正的 GET 请求。在效果上,具有与非ajax(非部分)提交完全相同的效果。在我的整个 JSF 职业生涯中,我遇到的唯一明智的用例是完整地显示错误页面,以防在 ajax 请求期间发生异常。另请参阅处理 AJAXified 组件的 JSF 2.0 异常的正确方法是什么?@all<a><h:link>?faces-redirect=trueExternalContext#redirect()process="@form" update="@all"@all

与特定于 PrimeFaces 的标准 JSF 等效于 。它的行为完全相同,只是它不支持逗号分隔的字符串,而 PrimeFaces 则支持(尽管我个人建议只坚持空格分隔的约定),也不支持关键字。both 和 默认值为 (即 “nothing”)。updaterender<f:ajax render>@parentupdaterender@none


另请参阅:

评论

0赞 K.Nicholas 12/19/2014
当我使用 update=“” 时,后备 Bean 的托管属性不会被设置,我的@PostConstruct例程失败。有什么想法吗?编辑:•如果依赖于后续 POST 请求中存在的 #{param} 的托管属性,则需要将其作为 <f:param> 包含在 UICommand 组件中。
0赞 bob-cac 7/25/2015
可能panelGroup的进程/更新将处理/更新此panelGroup的内容,例如: <h:panelGroup id=“pgId”>//输入文本在这里<h:panelGroup><p:commandLink process=“pgId” update=“pgId”/>
0赞 Rapster 11/21/2016
@BalusC 你说我们需要指出以防万一,以便调用操作,尽管如果我查看链接中的 Primefaces 展示没有设置并且效果很好,为什么会这样?@thisActionSourceprocess="@this"
2赞 BalusC 11/21/2016
@Rapster:因为没有设置,所以它使用默认值。这在上面的回答中也有解释。process@form
2赞 BalusC 5/13/2018
@Roland:它隐藏了一个不同的、更严重的应用程序配置问题。
64赞 Jaqen H'ghar 8/17/2014 #3

如果你很难记住默认值(我知道我有...),以下是 BalusC 答案的简短摘录:

元件 提交 刷新
f:阿贾克斯 执行=“@this” 渲染=“@none”
p:阿贾克斯 进程=“@this” 更新=“@none”
p:命令XXX 进程=“@form” 更新=“@none”

评论

0赞 Stephan Rauh 5/21/2016
只是一个小小的更正:for 的默认值是 。另外,这似乎适用于支持 AJAX 的每个组件,例如 .processp:commandXXX@allp:menuitem
1赞 Jaqen H'ghar 5/26/2016
嗨,@StephanRauh,非常感谢您的评论。你在哪里读到默认的?据我所知,从BalusC的答案中可以看出,它是,但是等价于进行中。关于其他组件的好点,我想我必须在有时间查看源代码以查看它适用于哪些组件,因为我宁愿不写可能错误的东西@all@form@all@form
1赞 Stephan Rauh 5/27/2016
@JaqenH托马斯·安德拉什科(Thomas Andraschko)告诉我这件事。他必须知道,他最近重新实现了PrimeFaces的AJAX引擎。后来,我仔细检查了它,但阅读了 PrimeFaces 的源代码并查看了 XHR 请求。我希望这次我做对了,因为我已经实现了 BootsFaces 的 AJAX 请求,以与 PrimeFaces 的 AJAX 请求相同的方式工作。@all
0赞 Marc Dzaebel 11/4/2018
如果说 HTML 不支持提交多个表单,则默认为 @all 会具有误导性。开发人员需要知道有效的默认值(以便 Thomas 可能会相应地更改它)。顺便说一句,这些默认值在 Primefaces 用户指南 6.2 中被错误地定义为 null。
11赞 Jasper de Vries 11/4/2019 #4

JSF 2.0+ 关键字

  • @this当前组件。
  • @all整个视图。
  • @form当前组件的最接近祖先形式。
  • @none无组件。

JSF 2.3+ 关键字

  • @child(n)第 n 个孩子。
  • @composite最接近的复合组件祖先。
  • @id(id)用于按组件的 ID 搜索组件,忽略组件树结构和命名容器。
  • @namingcontainer当前组件的最接近祖先命名容器。
  • @parent当前组件的父级。
  • @previous以前的兄弟姐妹。
  • @next下一个兄弟姐妹。
  • @rootUIViewRoot 实例,可用于从根而不是当前组件开始搜索。

PrimeFaces 特定关键字

  • @row(n)第 n 行。
  • @widgetVar(name)具有给定 widgetVar 的组件。

你甚至可以使用一种叫做“PrimeFaces Selectors”的东西,它允许你使用jQuery Selector API。例如,要使用 CSS 类处理元素中的所有输入:myClass

process="@(.myClass :input)"

看:

PrimeFaces 10+ 观察员 / 活动

这允许您根据关键字设置的自定义事件名称更新组件。例如:@obs(event)

<p:commandButton update="@obs(myEvent)"/>

<h:panelGroup>
    <p:autoUpdate on="myEvent"/>
</h:panelGroup>

看:

0赞 Alex Belke 5/19/2022 #5

这些是 PrimeFaces 功能,用于提供部分视图处理和部分渲染。您可以控制在生命周期中执行的内容以及使用 ajax 渲染的内容。

在表达式语言中使用后备 Bean 属性时

  • process 属性调用 SETTER 方法
  • update 属性调用 GETTER 方法

Primefaces论坛