了解PrimeFaces进程/更新和JSF f:ajax执行/渲染属性
PrimeFaces p:commandXxx
组件中的process
和update
以及f:ajax
标记中的execute
和render
是什么?
哪些在validation时有效? update
属性做什么而不是从后端更新值到组件? 做属性绑定值的模型? @form
@parent
, @form
@parent
, @form
@parent
和@parent
在两个属性中究竟做了什么?
下面的例子工作正常,但我基本概念有点困惑。
<p:commandButton process="@parent" update="@form" action="#{bean.submit}" value="Submit" />
<p:commandXxx process>
<p:ajax process>
<f:ajax execute>
process
属性是服务器端,只能影响实现EditableValueHolder
(input字段)或ActionSource
(命令字段)的UIComponent
。 process
属性告诉JSF,使用空格分隔的客户端ID列表,在(部分)表单提交时,完全必须通过整个JSF生命周期处理哪些组件。
然后,JSF将应用请求值(根据组件自己的客户端ID查找HTTP请求参数,然后将其设置为EditableValueHolder
组件的提交值或ActionSource
组件的情况下排队新的ActionEvent
),执行转换,validation和更新模型值(仅限EditableValueHolder
组件),最后调用排队的ActionEvent
( ActionSource
组件)。 JSF将跳过处理属性未覆盖的所有其他组件的process
。 另外,在应用请求值阶段期间rendered
属性评估为false
组件也将被跳过作为防范篡改请求的一部分。
请注意, ActionSource
组件(如<p:commandButton>
)的情况非常重要,因为您还将组件本身包含在process
属性中,特别是如果您打算调用与该组件相关联的操作。 所以下面的例子,当某个命令组件被调用时,只打算处理某些input组件是不行的:
<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>
如果表单中包含更多要处理的input组件,那么通常情况下,如果您希望根据当前input组件更新其他input组件或某个UI部分,一个ajax监听器方法。 您不希望其他input组件上的validation错误正在阻止执行ajax侦听器方法。
然后是@all
。 这在process
属性中没有特殊的效果,只有在update
属性中才有。 process="@all"
行为与process="@form"
行为完全相同。 HTML不支持一次提交多个表单。
还有一种方法@none
可能是有用的,如果你绝对不需要处理任何东西,但只想通过update
更新一些特定的部分,特别是那些内容不依赖于提交的值或动作侦听器的部分。
相当于PrimeFaces特定process
的标准JSF是从<f:ajax execute>
。 它的行为完全相同,只是它不支持以PrimeFaces做的逗号分隔的string(尽pipe我个人build议只@parent
空格分隔的约定),也不支持@parent
关键字。 另外,知道<p:commandXxx process>
默认为@form
而<p:ajax process>
和<f:ajax execute>
缺省为@this
可能会有帮助。 最后,了解该process
支持所谓的“PrimeFacesselect器”也很有用,参见update =“@(。myClass)”中的PrimeFacesselect器如何工作?
<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
)
虽然这可能工作正常,input和命令组件的更新在这个特殊的例子是不必要的。 除非你在action
方法里改变模型值foo
和bar
(这在UX的angular度上反过来是不直观的),所以没有必要更新它们。 消息组件是唯一真正需要更新的组件:
<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>
但是,当你有很多这样的东西时,这会变得乏味。 这就是PrimeFacesselect器存在的原因之一。 这些消息组件在生成的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)”中的PrimeFacesselect器如何工作?
@parent
只更新父组件,因此覆盖了当前组件以及所有兄弟和它们的子组件。 如果你们将自己的责任划分为理性的团体,这将更有用。 @this
更新,显然,只有当前组件。 通常,只有当您需要在操作方法中更改某个组件自己的HTML属性时才需要。 例如
<p:commandButton action="#{bean.action}" update="@this" oncomplete="doSomething('#{bean.value}')" />
想象一下,不完整的需要使用在action
改变的value
,那么如果组件没有被更新,这个构造就不会工作,原因在于, oncomplete
是生成的HTML输出的一部分(因此所有的ELexpression式在渲染响应期间评估)。
@all
更新整个文档,应该小心使用。 通常情况下,你想使用一个真正的GET请求,而不是通过一个简单的链接( <a>
或<h:link>
)或redirect后的?faces-redirect=true
或ExternalContext#redirect()
。 在效果中, process="@form" update="@all"
与非ajax(非部分)提交具有完全相同的效果。 在我的整个JSF职业生涯中,我遇到的唯一明智的用例就是在ajax请求发生exception的情况下,显示一个完整的错误页面。 另请参见处理AJAX化组件的JSF 2.0exception的正确方法是什么?
相当于PrimeFaces特定update
的标准JSF是从<f:ajax render>
。 它的行为完全相同,只是它不支持以PrimeFaces做的逗号分隔的string(尽pipe我个人build议只@parent
空格分隔的约定),也不支持@parent
关键字。 这两个update
和render
默认为@none
(即“没有”)。
也可以看看:
- 如何findajax更新/渲染组件的客户端ID? 无法find含有“bar”引用的expression式“foo”的组件
- 按下PrimeFaces p:commandButton时事件的执行顺序
- 在例如p:dataTable分页期间如何减lessp:ajax的请求负载
- 如何在p:对话框的p:dataTable中显示当前行的详细信息,并在保存后更新
- 如何在JSF页面中使用<h:form>? 单一forms? 多种forms? 嵌套表单?
如果你很难记住默认值(我知道我有…)这里有一个来自BalusC的答案的简短摘录:
组件| 提交| 刷新 ------------ | --------------- | -------------- f:ajax | execute =“@ this”| 渲染=“@无” p:ajax | process =“@ this”| 更新=“@无” p:commandXXX | process =“@ form”| 更新=“@无”
通过进程(在JSF规范中称为执行),您告诉JSF将处理限制为指定的组件,而其他指定的组件只是被忽略。
更新表示服务器回应您的请求时将更新哪个元素。
@all :每个组件都被处理/呈现。
@this :具有execute属性的请求组件被处理/呈现。
@form :处理/呈现包含请求组件的表单。
@parent :包含请求组件的父进程被处理/呈现。
有了Primefaces,你甚至可以使用JQueryselect器,看看这个博客: http ://blog.primefaces.org/?p=1867