了解PrimeFaces流程/更新和JSF f:ajax执行/渲染属性 [英] 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
属性是服务器端的属性,只能影响 ActionSource
(命令字段). process
属性使用空格分隔的客户端ID列表告诉JSF,在提交(部分)表单时,必须在整个JSF生命周期中准确处理哪些组件.
然后,JSF将应用请求值(根据组件自己的客户端ID查找HTTP请求参数,然后在 它只会处理 或者,就像您显然发现的那样,如果它们恰巧是唯一具有共同父代的组件,则使用 或者,如果它们都恰好是父级的唯一组件,则 如果表单包含您想在处理中跳过的更多输入组件,有时这是不希望的,而在您要基于当前更新其他输入组件或某些UI部分的情况下,这种情况通常会更多ajax侦听器方法中的输入组件.也就是说,您不希望其他输入组件上的验证错误阻止ajax侦听器方法的执行. 然后是 还有 请注意, 等同于PrimeFaces特定 然后,JSF将为此准备正确的ajax响应,其中仅包含 所请求的要更新的部分. JSF将跳过ajax响应中未被 通常,您只想 更新真正需要在(部分)表单提交时在客户端刷新"的组件.下面的示例通过 (请注意,省略了 尽管可以正常工作,但在此特定示例中,不需要更新输入和命令组件.除非您在 但是,当您有很多时,这将变得乏味.这就是PrimeFaces选择器存在的原因之一.这些消息组件在生成的HTML输出中具有 (请注意,您应将ID保留在消息组件上,否则 假设 与PrimeFaces特定 另请参见: What exactly are Which works at the time of validation? What does The example below is working fine, but I am a little confused in basic concepts.
The JSF will then apply the request values (finding HTTP request parameter based on component's own client ID and then either setting it as submitted value in case of Note that it's in case of It would only process the Or, as you apparently found out, using Or, if they both happen to be the only components of the parent This is sometimes undesirable if the form contains more input components which you'd like to skip in processing, more than often in cases when you'd like to update another input component(s) or some UI section based on the current input component in an ajax listener method. You namely don't want that validation errors on other input components are preventing the ajax listener method from being executed. Then there's the There's by the way also a Noted should be that the The standard JSF equivalent to the PrimeFaces specific The JSF will then prepare the right ajax response for that, containing only the requested parts to update. JSF will skip all other components which are not covered by Usually, you'd like to update only the components which really need to be "refreshed" in the client side upon (partial) form submit. The example below updates the entire parent form via (note that Whilst that may work fine, the update of input and command components is in this particular example unnecessary. Unless you change the model values However, that gets tedious when you have many of them. That's one of the reasons why PrimeFaces Selectors exist. Those message components have in the generated HTML output a common style class of (note that you should keep the IDs on message components, otherwise The Imagine that the The The standard JSF equivalent to the PrimeFaces specific See also: 这篇关于了解PrimeFaces流程/更新和JSF f:ajax执行/渲染属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!EditableValueHolder
组件的情况下将其设置为已提交值,或对新的#{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>
@all
.这在process
属性中没有特殊作用,而仅在update
属性中. process="@all"
的行为与process="@form"
完全相同. HTML不支持一次提交多个表单.@none
,如果您绝对不需要处理任何东西,但是 only 想要通过update
更新某些特定的部分,尤其是那些特定的部分,这可能会很有用内容不取决于提交的值或操作侦听器的部分.process
属性对HTTP请求有效负载(请求参数的数量)没有没有的影响.这意味着,发送<h:form>
的HTML表示中包含的所有内容"的默认HTML行为将不会受到影响.如果您的表单很大,并且希望将HTTP请求有效负载减少到仅在处理中绝对必要的那些,即仅将这些内容覆盖在process
属性中,则可以在PrimeFaces Ajax组件中将partialSubmit
属性设置为<p:commandXxx ... partialSubmit="true">
或<p:ajax ... partialSubmit="true">
.另外,您也可以使用OmniFaces 3.0+的 <o:form>
(默认为这种行为).>
process
的标准JSF是<f:ajax execute>
中的execute
.它的行为完全相同,不同之处在于它不支持逗号分隔的字符串,而PrimeFaces则支持(尽管我个人建议仅使用空格分隔的约定),也不支持@parent
关键字.同样,了解<p:commandXxx process>
默认为@form
而<p:ajax process>
和<f:ajax execute>
默认为@this
可能很有用.最后,知道process
支持所谓的"PrimeFaces Selectors"也很有用,另请参见
<p:commandXxx update>
<p:ajax update>
<f:ajax render>
update
属性是客户端,可以影响所有UIComponent
的HTML表示形式. update
属性使用空格分隔的客户端ID列表告诉JavaScript(负责处理ajax请求/响应的JavaScript),HTML DOM树中的哪些部分需要作为对表单提交的响应进行更新. update
属性覆盖的所有其他组件,从而使响应有效载荷保持较小.同样,在渲染响应阶段,其rendered
属性的值为c2的组件也将被跳过.请注意,即使最初返回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>
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>
@(...)
将不起作用!再次,请参见了解详情) @parent
仅更新父组件,从而覆盖了当前组件以及所有兄弟姐妹及其子代.如果您将表格分为理智的组别并各自负责,则此功能将更为有用.显然,@this
仅更新当前组件.通常,仅当您需要在action方法中更改组件自己的HTML属性之一时,才需要这样做.例如<p:commandButton action="#{bean.action}" update="@this"
oncomplete="doSomething('#{bean.value}')" />
oncomplete
需要与在action
中更改的value
一起使用,那么如果不更新组件,则此构造将无法工作,原因很简单,因为oncomplete
是生成的HTML输出的一部分(因此,其中的所有EL表达式都会在渲染响应期间进行评估).@all
更新整个文档,应谨慎使用.通常,您希望为此使用真正的GET请求,而不是通过纯链接(<a>
或<h:link>
)或通过?faces-redirect=true
或ExternalContext#redirect()
的POST后重定向.实际上,process="@form" update="@all"
具有与非ajax(非部分)提交完全相同的效果.在我整个JSF生涯中,我遇到的@all
唯一明智的用例是完整显示一个错误页面,以防ajax请求期间发生异常.另请参见处理AJAXified组件的JSF 2.0异常的正确方法是什么? update
等效的标准JSF是<f:ajax render>
中的render
.它的行为完全相同,不同之处在于它不支持逗号分隔的字符串,而PrimeFaces则支持(尽管我个人建议仅使用空格分隔的约定),也不支持@parent
关键字. update
和render
均默认为@none
(即无").
process
and update
in PrimeFaces p:commandXxx
components and execute
and render
in f:ajax
tag?update
attribute do rather than updating value to component from back end? Do process
attribute bind value to model? What exactly do @this
, @parent
, @all
and @form
in both attributes?<p:commandButton process="@parent"
update="@form"
action="#{bean.submit}"
value="Submit" />
<p:commandXxx process>
<p:ajax process>
<f:ajax execute>
process
attribute is server side and can only affect UIComponent
s implementing EditableValueHolder
(input fields) or ActionSource
(command fields). The process
attribute tells JSF, using a space-separated list of client IDs, which components exactly must be processed through the entire JSF lifecycle upon (partial) form submit. EditableValueHolder
components or queueing a new ActionEvent
in case of ActionSource
components), perform conversion, validation and updating the model values (EditableValueHolder
components only) and finally invoke the queued ActionEvent
(ActionSource
components only). JSF will skip processing of all other components which are not covered by process
attribute. Also, components whose rendered
attribute evaluates to false
during apply request values phase will also be skipped as part of safeguard against tampered requests.ActionSource
components (such as <p:commandButton>
) very important that you also include the component itself in the process
attribute, particularly if you intend to invoke the action associated with the component. So the below example which intends to process only certain input component(s) when a certain command component is invoked ain't gonna work:<p:inputText id="foo" value="#{bean.foo}" />
<p:commandButton process="foo" action="#{bean.action}" />
#{bean.foo}
and not the #{bean.action}
. You'd need to include the command component itself as well:<p:inputText id="foo" value="#{bean.foo}" />
<p:commandButton process="@this foo" action="#{bean.action}" />
@parent
if they happen to be the only components having a common 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
component, then you can also use @form
:<h:form>
<p:inputText id="foo" value="#{bean.foo}" />
<p:commandButton process="@form" action="#{bean.action}" />
</h:form>
@all
. This has no special effect in process
attribute, but only in update
attribute. A process="@all"
behaves exactly the same as process="@form"
. HTML doesn't support submitting multiple forms at once anyway.@none
which may be useful in case you absolutely don't need to process anything, but only want to update some specific parts via update
, particularly those sections whose content doesn't depend on submitted values or action listeners.process
attribute has no influence on the HTTP request payload (the amount of request parameters). Meaning, the default HTML behavior of sending "everything" contained within the HTML representation of the <h:form>
will be not be affected. In case you have a large form, and want to reduce the HTTP request payload to only these absolutely necessary in processing, i.e. only these covered by process
attribute, then you can set the partialSubmit
attribute in PrimeFaces Ajax components as in <p:commandXxx ... partialSubmit="true">
or <p:ajax ... partialSubmit="true">
. Alternatively, you can also use <o:form>
of OmniFaces 3.0+ which defaults to this behavior.process
is execute
from <f:ajax execute>
. It behaves exactly the same except that it doesn't support a comma-separated string while the PrimeFaces one does (although I personally recommend to just stick to space-separated convention), nor the @parent
keyword. Also, it may be useful to know that <p:commandXxx process>
defaults to @form
while <p:ajax process>
and <f:ajax execute>
defaults to @this
. Finally, it's also useful to know that process
supports the so-called "PrimeFaces Selectors", see also How do PrimeFaces Selectors as in update="@(.myClass)" work?
<p:commandXxx update>
<p:ajax update>
<f:ajax render>
update
attribute is client side and can affect the HTML representation of all UIComponent
s. The update
attribute tells JavaScript (the one responsible for handling the ajax request/response), using a space-separated list of client IDs, which parts in the HTML DOM tree need to be updated as response to the form submit. update
attribute in the ajax response, hereby keeping the response payload small. Also, components whose rendered
attribute evaluates to false
during render response phase will be skipped. Note that even though it would return true
, JavaScript cannot update it in the HTML DOM tree if it was initially false
. You'd need to wrap it or update its parent instead. See also 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
attribute is omitted as that defaults to @form
already)foo
and bar
inside action
method (which would in turn be unintuitive in UX perspective), there's no point of updating them. The message components are the only which really need to be updated:<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>
ui-message
, so the following should also do:<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>
@(...)
won't work! Again, see How do PrimeFaces Selectors as in update="@(.myClass)" work? for detail)@parent
updates only the parent component, which thus covers the current component and all siblings and their children. This is more useful if you have separated the form in sane groups with each its own responsibility. The @this
updates, obviously, only the current component. Normally, this is only necessary when you need to change one of the component's own HTML attributes in the action method. E.g.<p:commandButton action="#{bean.action}" update="@this"
oncomplete="doSomething('#{bean.value}')" />
oncomplete
needs to work with the value
which is changed in action
, then this construct wouldn't have worked if the component isn't updated, for the simple reason that oncomplete
is part of generated HTML output (and thus all EL expressions in there are evaluated during render response).@all
updates the entire document, which should be used with care. Normally, you'd like to use a true GET request for this instead by either a plain link (<a>
or <h:link>
) or a redirect-after-POST by ?faces-redirect=true
or ExternalContext#redirect()
. In effects, process="@form" update="@all"
has exactly the same effect as a non-ajax (non-partial) submit. In my entire JSF career, the only sensible use case I encountered for @all
is to display an error page in its entirety in case an exception occurs during an ajax request. See also What is the correct way to deal with JSF 2.0 exceptions for AJAXified components?update
is render
from <f:ajax render>
. It behaves exactly the same except that it doesn't support a comma-separated string while the PrimeFaces one does (although I personally recommend to just stick to space-separated convention), nor the @parent
keyword. Both update
and render
defaults to @none
(which is, "nothing").