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

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

哪些在验证时有效? 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属性是服务器端,只能影响实现EditableValueHolder (输入字段)或ActionSource (命令字段)的UIComponentprocess属性告诉JSF,使用空格分隔的客户端ID列表,在(部分)表单提交时,完全必须通过整个JSF生命周期处理哪些组件。

然后,JSF将应用请求值(根据组件自己的客户端ID查找HTTP请求参数,然后在EditableValueHolder组件的情况下将其设置为提交的值,或者在ActionSource组件的情况下排队新的ActionEvent ),执行转换,验证和更新模型值(仅限EditableValueHolder组件),最后调用排队的ActionEventActionSource组件)。 JSF将跳过对process属性未涉及的所有其他组件的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更新某些特定部分,特别是那些内容不依赖于提交的值或动作侦听器的部分。

该JSF标准等同于PrimeFaces具体processexecute<f:ajax execute> 。 它的行为完全一样,只不过它不支持逗号分隔的字符串,而PrimeFaces却不支持(尽管我个人建议只坚持空格分隔的约定),也不支持@parent关键字。 另外,知道<p:commandXxx process>默认为@form<p:ajax process><f:ajax execute>默认为@this可能会很有用。 最后,了解该process支持所谓的“PrimeFaces选择器”也很有用,另请参阅PrimeFaces选择器如update =“@(。myClass)”的工作方式?


<p:commandXxx update> <p:ajax update> <f:ajax render>

update属性是客户端,可以影响所有UIComponent的HTML表示。 update属性告诉JavaScript(负责处理ajax请求/响应的那个),使用空格分隔的客户端ID列表,HTML格式树中的哪些部分需要更新,以响应表单提交。

然后,JSF将为此准备正确的ajax响应,仅包含要更新的请求部分。 JSF将跳过ajax响应中没有被update属性覆盖的所有其他组件,因此保持响应有效负载很小。 此外,在呈现响应阶段rendered属性评估为false组件将被跳过。 请注意,即使它返回true ,JavaScript也无法在HTML DOM树中更新它,如果它最初是false 。 您需要将其包装或更新其父项。 另请参见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方法中改变模型值foobar (这在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,否则@(...)将不起作用!请再次参阅update =“@(。myClass)”中的PrimeFaces选择器如何工作以获取详细信息)

@parent只更新父组件,它涵盖了当前组件以及所有兄弟姐妹及其子组件。 如果你将表格分成了自己的团队和每个人自己的责任,这会更有用。 @this显然只更新当前组件。 通常,只有当您需要在操作方法中更改某个组件自己的HTML属性时才需要。 例如

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

想象oncomplete需要与工作value这是在改变action ,那么如果组件未更新,原因很简单,这个结构就不会工作oncomplete因此所有EL表达式生成的HTML输出的一部分(和在渲染响应期间评估)。

@all更新整个文档,应谨慎使用。 通常情况下,您希望对此使用真正的GET请求,而不是通过简单链接( <a><h:link> )或者通过?faces-redirect=trueExternalContext#redirect()后的POST ExternalContext#redirect() 。 在效果中, process="@form" update="@all"与非ajax(非部分)提交具有完全相同的效果。 在我的整个JSF职业生涯中,我遇到的@all唯一合理的用例是在ajax请求发生异常的情况下全部显示错误页面。 另请参见处理AJAX化组件的JSF 2.0异常的正确方法是什么?

该JSF标准等同于PrimeFaces特定updaterender<f:ajax render> 。 它的行为完全一样,只不过它不支持逗号分隔的字符串,而PrimeFaces却不支持(尽管我个人建议只坚持空格分隔的约定),也不支持@parent关键字。 updaterender默认为@none (即“没有”)。


也可以看看:

  • 如何找出ajax更新/渲染组件的客户端ID? 找不到带有“bar”引用的表达式“foo”的组件
  • 按PrimeFaces p:commandButton时事件的执行顺序
  • 如何在例如p:dataTable分页期间减少p:ajax的请求负载
  • 如何在p:对话框中显示来自p:dataTable的当前行的详细信息,并在保存后进行更新
  • 如何在JSF页面中使用<h:form>? 单一形式? 多种形式? 嵌套表单?

  • 如果你很难记住默认值(我知道我有......),这里有一个来自BalusC的答案的简短摘录:

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

    按照流程(在JSF规范中称为execute),您告诉JSF将处理限制为只是被忽略的其他指定的组件。

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

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

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

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

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

    有了Primefaces,你甚至可以使用JQuery选择器,看看这个博客:http://blog.primefaces.org/?p=1867

    链接地址: http://www.djcxy.com/p/71661.html

    上一篇: Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes

    下一篇: Several messages programmatically in JSF