[英]Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes
PrimeFaces p:commandXxx
组件中的process
和update
以及在f:ajax
标签中execute
和render
的具体内容是什么?
验证时哪个有效? update
属性做什么而不是从后端更新组件的值? process
属性是否将值绑定到模型? @this
、 @parent
、 @all
和@form
在这两个属性中到底是什么?
下面的示例运行良好,但我对基本概念有点困惑。
<p:commandButton process="@parent"
update="@form"
action="#{bean.submit}"
value="Submit" />
<p:commandXxx process>
<p:ajax process>
<f:ajax execute>
process
属性是服务器端的,只能影响UIComponent
实现EditableValueHolder
(输入字段)或ActionSource
(命令字段)。 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
属性,如<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 特定process
等效的标准 JSF 是从<f:ajax execute>
execute
。 它的行为完全相同,只是它不支持逗号分隔的字符串,而 PrimeFaces 支持(尽管我个人建议只坚持空格分隔的约定),也不@parent
关键字。 此外,了解<p:commandXxx process>
默认为@form
而<p:ajax process>
和<f:ajax execute>
默认为@this
可能很有用。 最后,了解process
支持所谓的“PrimeFaces 选择器”也很有用,另请参阅update="@(.myClass)" 中的 PrimeFaces 选择器如何工作?
<p:commandXxx update>
<p:ajax update>
<f:ajax render>
update
属性是客户端的,可以影响所有UIComponent
的 HTML 表示。 update
属性告诉 JavaScript(负责处理 ajax 请求/响应的),使用空格分隔的客户端 ID 列表,HTML DOM 树中的哪些部分需要更新作为对表单提交的响应。
然后 JSF 将为此准备正确的 ajax 响应,其中仅包含要更新的请求部分。 JSF 将跳过 ajax 响应中update
属性未涵盖的所有其他组件,从而使响应负载保持较小。 此外,在渲染响应阶段rendered
属性评估为false
的组件将被跳过。 请注意,即使它会返回true
,如果它最初为false
,JavaScript 也无法在 HTML DOM 树中更新它。 您需要将其包装或更新其父级。 另请参阅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
)
虽然这可能工作正常,但在这个特定示例中,输入和命令组件的更新是不必要的。 除非您在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,否则@(...)
将不起作用!再次,请参阅PrimeFaces 选择器如何在 update="@(.myClass)" 中工作?有关详细信息)
@parent
仅更新父组件,从而覆盖当前组件和所有兄弟姐妹及其子组件。 如果您将表单分成不同的组并各自负责,这将更加有用。 @this
显然只更新当前组件。 通常,只有当您需要在 action 方法中更改组件自己的 HTML 属性之一时,才需要这样做。 例如
<p:commandButton action="#{bean.action}" update="@this"
oncomplete="doSomething('#{bean.value}')" />
想象一下oncomplete
需要使用在action
中改变的value
,那么如果组件没有更新,这个构造就不会起作用,原因很简单, oncomplete
是生成的 HTML 输出的一部分(因此所有 EL 表达式在渲染响应期间进行评估)。
@all
更新整个文档,应该小心使用。 通常,您希望通过普通链接( <a>
或<h:link>
)或通过?faces-redirect=true
或ExternalContext#redirect()
. 实际上, process="@form" update="@all"
与非 ajax(非部分)提交的效果完全相同。 在我的整个 JSF 职业生涯中,我遇到的唯一一个对@all
有意义的用例是在 ajax 请求期间发生异常时完整地显示一个错误页面。 另请参阅处理 AJAX 化组件的 JSF 2.0 异常的正确方法是什么?
与 PrimeFaces 特定update
等效的标准 JSF 是从<f:ajax render>
render
。 它的行为完全相同,只是它不支持逗号分隔的字符串,而 PrimeFaces 支持(尽管我个人建议只坚持空格分隔的约定),也不@parent
关键字。 update
和render
都默认为@none
(即“无”)。
也可以看看:
如果您很难记住默认值(我知道我有...),这里是 BalusC 答案的简短摘录:
零件 | 提交 | 刷新 |
---|---|---|
f:ajax | 执行="@this" | 渲染="@none" |
p:ajax | 进程="@this" | 更新=“@无” |
p:commandXXX | 进程="@form" | 更新=“@无” |
通过进程(在 JSF 规范中它被称为执行),您告诉 JSF 将处理限制为指定的组件,其他所有内容都将被忽略。
update 指示当服务器响应您的请求时将更新哪个元素。
@all :每个组件都被处理/渲染。
@this :具有执行属性的请求组件被处理/呈现。
@form :处理/呈现包含请求组件的表单。
@parent :处理/渲染包含请求组件的父级。
使用 Primefaces,您甚至可以使用 JQuery 选择器,请查看此博客: http ://blog.primefaces.org/?p=1867
@this
当前组件。@all
整个视图。@form
当前组件的最近祖先形式。@none
没有组件。@child(n)
第 n 个孩子。@composite
最近的复合组件祖先。@id(id)
用于通过 id 搜索组件,忽略组件树结构和命名容器。@namingcontainer
当前组件最近的祖先命名容器。@parent
当前组件的父级。@previous
上一个兄弟姐妹。@next
下一个兄弟姐妹。@root
UIViewRoot 视图的实例,可用于从根而不是当前组件开始搜索。@row(n)
第 n 行。@widgetVar(name)
具有给定 widgetVar 的组件。 你甚至可以使用一种叫做“PrimeFaces Selectors”的东西,它允许你使用 jQuery Selector API。 例如,使用 CSS 类myClass
处理元素中的所有输入:
process="@(.myClass :input)"
看:
这允许您根据由@obs(event)
关键字设置的自定义事件名称来更新组件。 例如:
<p:commandButton update="@obs(myEvent)"/>
<h:panelGroup>
<p:autoUpdate on="myEvent"/>
</h:panelGroup>
看:
这些是提供部分视图处理和部分渲染的 PrimeFaces 功能。 您可以控制在生命周期中执行什么以及使用 ajax 呈现什么。
在表达式语言中使用支持 bean 属性时
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.