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

PrimeFaces p:commandXxx组件中的processupdate以及f:ajax标记中的executerender是什么?

哪些在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 (命令字段)的UIComponentprocess属性告诉JSF,使用空格分隔的客户端ID列表,在(部分)表单提交时,完全必须通过整个JSF生命周期处理哪些组件。

然后,JSF将应用请求值(根据组件自己的客户端ID查找HTTP请求参数,然后将其设置为EditableValueHolder组件的提交值或ActionSource组件的情况下排队新的ActionEvent ),执行转换,validation和更新模型值(仅限EditableValueHolder组件),最后调用排队的ActionEventActionSource组件)。 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方法里改变模型值foobar (这在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=trueExternalContext#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关键字。 这两个updaterender默认为@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