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

时间:2014-08-16 10:02:08

标签: jsf primefaces process updates

PrimeFaces process组件中的updatep:commandXxxexecute标记中的renderf:ajax究竟是什么?

验证时哪个有效? update属性做什么而不是从后端更新组件的值? process属性绑定值是否为模型?这两个属性中究竟有@this@parent@all@form到底是什么?

以下示例工作正常,但我对基本概念感到困惑。

<p:commandButton process="@parent"
                 update="@form"
                 action="#{bean.submit}" 
                 value="Submit" />

4 个答案:

答案 0 :(得分:272)

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

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

然后,JSF将应用请求值(根据组件自己的客户端ID查找HTTP请求参数,然后在EditableValueHolder组件的情况下将其设置为提交值或排队新{{3}在ActionSource组件的情况下),执行转换,验证和更新模型值(仅EditableValueHolder组件),最后仅调用排队的ActionEventActionSource组件)。 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>

或者,如果它们恰好是父ActionEvent组件的唯一组件,那么您也可以使用@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请求有效负载(请求参数的数量)有 no 影响。意思是,发送&#34;所有内容的默认HTML行为&#34;包含在<h:form>的HTML表示中的内容不会受到影响。如果您有一个大型表单,并希望将HTTP请求有效负载减少到只有处理中绝对必要的那些,即只有process属性涵盖的那些,那么您可以在PrimeFaces Ajax中设置partialSubmit属性<p:commandXxx ... partialSubmit="true"><p:ajax ... partialSubmit="true">中的组件。或者,您也可以使用默认为此行为的UIForm OmniFaces 3.0+。

process相当于PrimeFaces特定execute的标准JSF是<f:ajax execute>。它的行为完全相同,只是它不支持逗号分隔的字符串,而PrimeFaces字符串(虽然我个人建议只是坚持空格分隔的约定),而不是@parent关键字。此外,知道<p:commandXxx process>默认为@form<p:ajax process><f:ajax execute>默认为@this可能会有用。最后,了解process支持所谓的&#34; PrimeFaces选择器&#34;也很有用,另请参阅<o:form>


<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树中更新它。您需要将其换行或更新其父级。另请参阅How do PrimeFaces Selectors as in update="@(.myClass)" work?

通常,您只想更新 在客户端(部分)表单提交。以下示例通过@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

虽然这可能工作正常,但输入和命令组件的更新在此特定示例中是不必要的。除非您在foo方法中更改模型值baraction(在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,否则@(...)无法正常工作!再次,请参阅Ajax update/render does not work on a component which has rendered attribute了解详细信息)

@parent仅更新父组件,从而覆盖当前组件及所有兄弟姐妹及其子组件。如果您将表单中的表单与每个自己的职责分开,这将更有用。 @this显然只更新当前组件。通常,仅当您需要在操作方法中更改组件的某个HTML属性时,才需要这样做。 E.g。

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

想象一下,oncomplete需要使用value中更改的action,如果组件未更新,则此构造不起作用,原因很简单oncomplete是生成的HTML输出的一部分(因此在渲染响应期间评估其中的所有EL表达式)。

@all更新整个文档,应谨慎使用。通常情况下,您希望通过普通链接(<a><h:link>)或?faces-redirect=true或{之后的重定向 - POST来使用真正的GET请求。 {1}}。在效果中,ExternalContext#redirect()与非ajax(非部分)提交具有完全相同的效果。在我的整个JSF职业生涯中,我遇到的process="@form" update="@all"唯一明智的用例是在ajax请求期间发生异常时完整显示错误页面。另请参阅How do PrimeFaces Selectors as in update="@(.myClass)" work?

@all相当于PrimeFaces特定update的标准JSF是render。它的行为完全相同,只是它不支持逗号分隔的字符串,而PrimeFaces字符串(虽然我个人建议只是坚持空格分隔的约定),而不是<f:ajax render>关键字。 @parentupdate都默认为render(即#34;没有&#34;)。


另见:

答案 1 :(得分:49)

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

Component    | Submit          | Refresh
------------ | --------------- | --------------
f:ajax       | execute="@this" | render="@none"
p:ajax       | process="@this" | update="@none"
p:commandXXX | process="@form" | update="@none"

答案 2 :(得分:23)

通过进程(在JSF规范中它被称为execute),您告诉JSF将处理限制为指定的组件,其他任何东西都被忽略。

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

@all :处理/呈现每个组件。

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

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

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

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

答案 3 :(得分:1)

请注意,PrimeFaces支持标准的JSF 2.0+关键字:

  • @this当前组件。
  • @all整个视图。
  • @form当前组件的最接近祖先形式。
  • @none没有组成部分。

和标准的JSF 2.3+关键字:

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

但是,它也带有一些PrimeFaces特定关键字:

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

您甚至可以使用名为“ PrimeFaces Selectors”的东西,它使您可以使用jQuery Selector API。例如,使用CSS类myClass处理元素中的所有输入:

process="@(.myClass :input)"

请参阅: