首页 文章

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

提问于
浏览
165

PrimeFaces p:commandXxx 组件中的 processupdate 究竟是什么, f:ajax 标签中的 executerender 究竟是什么?

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

以下示例工作正常,但我对基本概念有点困惑 .

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

3 回答

  • 262

    <p:commandXxx进程> <p:ajax进程> <f:ajax execute>

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

    然后,JSF将应用请求值(根据组件自己的客户端ID查找HTTP请求参数,然后在 EditableValueHolder 组件的情况下将其设置为提交值,或者在 ActionSource 组件的情况下将新的ActionEvent排队),执行转换,验证和更新模型值(仅限 EditableValueHolder 组件),最后调用排队的 ActionEvent (仅限 ActionSource 组件) . JSF将跳过 process 属性未涵盖的所有其他组件的处理 . 此外,在应用请求值阶段期间 rendered 属性求值为 false 的组件也将被跳过,作为防止篡改请求的一部分 .

    请注意,在 ActionSource 组件(例如 <p:commandButton> )的情况下,非常重要的是您还要在 process 属性中包含组件本身,特别是如果您打算调用与组件关联的操作 . 所以下面的例子打算在调用某个命令组件时只处理某些输入组件是不行的:

    <p:inputText id="foo" value="#{bean.foo}" />
    <p:commandButton process="foo" action="#{bean.action}" />
    

    它只会处理 #{bean.foo}not #{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 更新某些特定部分,特别是那些内容不依赖于提交值或动作侦听器的部分,这可能很有用 .

    注意应该是 process 属性对HTTP请求有效负载(请求参数的数量)有 no 影响 . 意思是, <h:form> 的HTML表示中包含的发送"everything"的默认HTML行为将不受影响 . 如果您有一个大型表单,并希望将HTTP请求有效负载减少到只有处理中绝对必要的那些,即只有 process 属性所涵盖的那些,那么您可以在 <p:commandXxx ... partialSubmit="true"><p:ajax ... partialSubmit="true"> 中设置PrimeFaces Ajax组件中的 partialSubmit 属性 . 或者,您也可以使用<o:form> OmniFaces 3.0,默认为此行为 .

    相当于PrimeFaces特定 process 的标准JSF是 execute 来自 <f:ajax execute> . 它的行为完全相同,只是它不支持逗号分隔的字符串而PrimeFaces字符串(虽然我个人建议只是坚持空格分隔的约定),也不支持 @parent 关键字 . 此外,知道 <p:commandXxx process> 默认为 @form<p:ajax process><f:ajax execute> 默认为 @this 可能很有用 . 最后,知道 process 支持所谓的"PrimeFaces Selectors"也很有用,另见How do PrimeFaces Selectors as in update="@(.myClass)" work?


    <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 update/render does not work on a component which has rendered attribute .

    通常,您希望在(部分)表单提交时仅更新客户端中真正需要"refreshed"的组件 . 以下示例通过 @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,否则 @(...) 将无效!再次参见How do PrimeFaces Selectors as in update="@(.myClass)" work?了解详细信息)

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

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

    想象一下 oncomplete 需要使用 value 中更改的 value ,然后这个构造不会更新,原因很简单 oncomplete 是生成的HTML输出的一部分(因此在渲染响应期间评估其中的所有EL表达式) .

    @all 更新整个文档,应谨慎使用 . 通常,您希望通过普通链接( <a><h:link> )或 ?faces-redirect=trueExternalContext#redirect() 之后的重定向后POST来使用真正的GET请求 . 在效果中, process="@form" update="@all" 与非ajax(非部分)提交具有完全相同的效果 . 在我的整个JSF职业生涯中,我遇到的 @all 唯一明智的用例是在ajax请求期间发生异常时完整显示错误页面 . 另见What is the correct way to deal with JSF 2.0 exceptions for AJAXified components?

    相当于PrimeFaces特定 update 的标准JSF是 render 来自 <f:ajax render> . 它的行为完全相同,只是它不支持逗号分隔的字符串,而PrimeFaces字符串(虽然我个人建议只是坚持空格分隔的约定),也不支持 @parent 关键字 . updaterender 都默认为 @none (即"nothing") .


    See also:

  • 22

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

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

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

    update指示当服务器响应您的请求时将更新哪个元素 .

    @all :处理/渲染每个组件 .

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

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

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

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

相关问题