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


193

究竟是什么process,并update在PrimeFaces p:commandXxx组件和executerenderf:ajax标签?

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

下面的示例工作正常,但是我对基本概念有些困惑。

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

Answers:


306

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

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

然后JSF将应用请求的值(发现基于组件自己的客户端ID的HTTP请求的参数,然后要么在的情况下,将其设置为提交的值EditableValueHolder的部件或排队新ActionEvent中的情况下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>

或者,如果它们都恰好是父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请求有效负载(请求参数的数量)没有影响。意思是,发送的HTML表示中包含的“所有内容”的默认HTML行为<h:form>不会受到影响。如果您的表单很大,并且希望将HTTP请求有效负载减少到仅在处理中绝对必要的那些,即仅将这些process属性覆盖,则可以partialSubmit<p:commandXxx ... partialSubmit="true">或中的PrimeFaces Ajax组件中设置该属性<p:ajax ... partialSubmit="true">。您还可以通过编辑web.xml和添加“全局”配置

<context-param>
    <param-name>primefaces.SUBMIT</param-name>
    <param-value>partial</param-value>
</context-param>

另外,您也可以使用<o:form>默认为这种行为的OmniFaces 3.0+。

JSF的同等标准的PrimeFaces具体processexecute<f:ajax execute>。它的行为完全相同,不同之处在于它不支持逗号分隔的字符串,而PrimeFaces则支持(尽管我个人建议仅使用空格分隔的约定),也不支持@parent关键字。同样,了解<p:commandXxx process>默认值为@formwhile <p:ajax process><f:ajax execute>默认值为可能会很有用@this。最后,知道process支持所谓的“ PrimeFaces Selectors” 也很有用,另请参见update =“ @(。myClass)”中的PrimeFaces Selectors如何工作?


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

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

然后,JSF将为此准备正确的ajax响应,其中包含需要更新的部分。JSF将跳过updateajax响应中属性未涵盖的所有其他组件,从而使响应有效载荷保持较小。同样,其rendered属性false在渲染响应阶段评估为的组件也将被跳过。请注意,即使它返回了true,JavaScript最初也无法在HTML DOM树中对其进行更新false。您需要包装它或更新其父代。另请参见Ajax update / render在具有rendered属性的组件上不起作用

通常,您只想更新(部分)表单提交时真正需要在客户端“刷新” 的组件。下面的示例通过来更新整个父表单@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已经存在)

尽管可以正常工作,但在此特定示例中无需更新输入和命令组件。除非您更改模型值foobar内部action方法(这在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 Selectors如何工作以了解详细信息)

@parent仅更新父组件,因此其覆盖电流分量和所有的兄弟姐妹和他们的孩子。如果您将表格分为理智的组别并各自负责,则此功能将更为有用。该@this更新,显然,只有电流分量。通常,仅在需要在action方法中更改组件自己的HTML属性之一时才需要这样做。例如

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

想象一下,在中更改了的oncomplete需求,那么,如果不更新组件,则此构造将无法正常工作,原因很简单,因为它是生成的HTML输出的一部分(因此对其中的所有EL表达式进行了求值在渲染响应期间)。valueactiononcomplete

@all更新整个文件,这应小心使用。通常情况下,你想通过代替或者是一个普通的链接(使用这个真正的GET请求<a><h:link>)或重定向消息后发表?faces-redirect=trueExternalContext#redirect()。在效果上,process="@form" update="@all"与非ajax(非部分)提交具有完全相同的效果。在我整个JSF生涯中,我遇到的唯一明智的用例@all是完整显示一个错误页面,以防ajax请求期间发生异常。另请参见处理AJAXified组件的JSF 2.0异常的正确方法是什么?

JSF的同等标准的PrimeFaces具体updaterender<f:ajax render>。它的行为完全相同,不同之处在于它不支持逗号分隔的字符串,而PrimeFaces则支持(尽管我个人建议仅使用空格分隔的约定),也不支持@parent关键字。双方updaterender默认为@none(这是“无”)。


也可以看看:


当我使用update =“”时,备用Bean的托管属性未设置,并且我的@PostConstruct例程失败。有什么想法吗?编辑:•如果您依靠#{param}的托管属性出现在后续的POST请求中,则需要在UICommand组件中将其作为<f:param>包括在内。
K.Nicholas 2014年

可能是panelGroup的处理/更新将处理/更新此panelGroup的内容,例如:<h:panelGroup id =“ pgId”> ///此处输入的文本<h:panelGroup> <p:commandLink process =“ pgId”更新=“ pgId” />
bob-cac

Thx @BalusC提供了非常好的解释!
ProgrammingIsAwsome

2
@Rapster:因为process未设置,所以它使用默认值@form。以上答案中也对此进行了解释。
BalusC

2
@Roland:它在应用程序配置中隐藏了另一个更严重的问题。
BalusC

54

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

组件| 提交| 刷新
------------ | --------------- | --------------
f:ajax | execute =“ @ this” | render =“ @ none”
p:ajax | process =“ @ this” | update =“ @ none”
p:commandXXX | process =“ @ form” | update =“ @ none”

只是一个小小的更正:processfor 的默认值p:commandXXX@all。另外,这似乎适用于支持AJAX的每个组件,例如p:menuitem
斯蒂芬·劳

1
嗨@StephanRauh,非常感谢您的评论。您在哪里读到的默认值是@all?据我从BalusC的答案中可以看出,它是@form,但是@all等效@form于过程。关于其他组件的要点,我想我需要在时间上查看源代码以了解其适用于哪些组件,因为我宁愿不要写可能出错的东西
Jaqen H'ghar

1
@ JaqenH'ghar托马斯·安德拉奇科(Thomas Andraschko)向我介绍了这@all一点。他必须知道,他最近重新实现了PrimeFaces的AJAX引擎。后来,我仔细检查了一下,但阅读了PrimeFaces的源代码并查看了XHR请求。我希望这次我做对了,因为我已经实现了BootsFaces的AJAX请求,使其与PrimeFaces的AJAX请求完全一样。
Stephan Rauh

如果HTML不支持多种形式的提交,那么默认值为@all可能会引起误解。开发人员需要知道有效的默认值(因此Thomas可能会相应地对其进行更改)。顺便说一句,在《 Primefaces用户指南6.2》中将这些默认值错误地定义为null。
马克·扎贝尔

27

通过流程(在JSF规范中称为执行),您告诉JSF将处理限制在指定的组件上,而忽略所有其他内容。

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

@all:每个组件都已处理/渲染。

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

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

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

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


2

请注意,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)"

看到:


2
请注意,即使JSF2.3 +也支持大多数关键字。
tandraschko '19
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.