PrimeFaces process组件中的updatep:commandXxx以及execute标签中的renderf:ajax到底是什么?

验证时哪些工作? update属性做什么,而不是从后端将值更新为组件? process属性将值绑定到模型吗?两个属性中的@this@parent@all@form到底是什么?

下面的示例可以正常工作,但是我在基本概念上有些困惑。 />

#1 楼


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

process属性是服务器端,仅影响UIComponent实现EditableValueHolder(输入字段)或ActionSource(命令字段)的属性。 process属性使用空格分隔的客户端ID列表告诉JSF,在提交(部分)表单时,必须在整个JSF生命周期中完全处理哪些组件。
然后,JSF将应用请求值(查找HTTP请求参数)根据组件自己的客户端ID,然后在EditableValueHolder组件的情况下将其设置为提交的值,或者在ActionEvent组件的情况下将其排入新的ActionSource),执行转换,验证和更新模型值(仅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}而不处理#{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请求有效负载(请求参数的数量)没有影响。这意味着,发送包含在<h:form>的HTML表示中的“所有内容”的默认HTML行为将不会受到影响。如果您的表单很大,并且希望将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>

来“全局”配置此方法,或者,也可以使用默认为此行为的OmniFaces 3.0+的<o:form>
等效于PrimeFaces特定process的标准JSF是execute中的<f:ajax execute>。它的行为完全相同,不同之处在于它不支持逗号分隔的字符串,而PrimeFaces则支持(尽管我个人建议仅使用空格分隔的约定),也不支持@parent关键字。另外,知道<p:commandXxx process>默认为@form,而<p:ajax process><f:ajax execute>默认为@this可能很有用。最后,知道process支持所谓的“ PrimeFaces选择器”也很有用,另请参见update =“ @(。myClass)”中的PrimeFaces选择器如何工作?


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

update属性是客户端,可以影响所有UIComponent的HTML表示形式。 update属性使用空格分隔的客户端ID列表告诉JavaScript(负责处理ajax请求/响应的属性),HTML DOM树中的哪些部分需要更新以响应表单提交。
然后,JSF将为此准备正确的ajax响应,其中仅包含需要更新的部分。 JSF将跳过ajax响应中update属性未涵盖的所有其他组件,从而使响应有效载荷保持较小。同样,在渲染响应阶段其rendered属性评估为false的组件也将被跳过。请注意,即使它返回true,但如果最初是false,JavaScript都无法在HTML DOM树中对其进行更新。您需要包装它或更新其父代。另请参见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
尽管可以正常工作,但在此特定示例中无需更新输入和命令组件。除非您在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保留在消息组件上,否则@(...)将不起作用再次,请参见update =“ @(。myClass)”中的PrimeFaces Selectors的工作原理以了解详细信息)
@parent仅更新父组件,从而覆盖了当前组件以及所有同级组件及其子级。如果您将表格分成理智的小组并各自负责,则此功能将更为有用。显然,@this仅更新当前组件。通常,仅在需要在action方法中更改组件自己的HTML属性之一时才需要这样做。例如,假设oncomplete需要与在value中更改的action一起使用,那么如果不更新组件,则该构造将无法正常工作,原因很简单,因为oncomplete是其中的一部分生成的HTML输出(因此在渲染响应期间将评估其中的所有EL表达式)。
@all更新了整个文档,应谨慎使用。通常,您想为此使用真正的GET请求,而不是通过纯链接(<a><h:link>)或通过?faces-redirect=trueExternalContext#redirect()进行POST重定向。实际上,process="@form" update="@all"具有与非ajax(非部分)提交完全相同的效果。在我整个JSF生涯中,遇到@all的唯一明智的用例是完整显示一个错误页面,以防ajax请求期间发生异常。另请参见处理AJAX化组件的JSF 2.0异常的正确方法是什么?
与PrimeFaces特定update等效的标准JSF是render中的<f:ajax render>。它的行为完全相同,不同之处在于它不支持逗号分隔的字符串,而PrimeFaces则支持(尽管我个人建议仅使用空格分隔的约定),也不支持@parent关键字。 updaterender都默认为@none(即“无”)。

另请参见:

如何找出要进行Ajax更新/渲染的组件的客户端ID?在按PrimeFaces p:commandButton
时如何找不到从“ bar”引用的表达式为“ foo”的组件。 p:dataTable分页
如何在p:dialog中显示p:dataTable中当前行的详细信息,并保存后进行更新
如何在JSF页面中使用?单一表格?多种形式?嵌套表格?


评论


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

– K.Nicholas
2014-12-18 21:03



可能是panelGroup的处理/更新将处理/更新这个panelGroup的内容,例如: //输入文本在这里

– bob-cac
15年7月25日在6:08

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

–ProgrammingIssome
16年1月22日在10:01

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

– BalusC
16-11-21在10:58



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

– BalusC
18年5月13日在8:34

#2 楼

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

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


评论


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

–斯蒂芬·劳(Stephan Rauh)
16年5月21日在13:22



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

– Jaqen H'ghar
16年5月26日在6:34

@ JaqenH'ghar Thomas Andraschko告诉了我@all的全部情况。他必须知道,他最近重新实现了PrimeFaces的AJAX引擎。后来,我仔细检查了一下,但阅读了PrimeFaces的源代码并查看了XHR请求。我希望这次我做对了,因为我已经实现了BootsFaces的AJAX请求,使其与PrimeFaces的AJAX请求相同。

–斯蒂芬·劳(Stephan Rauh)
16年5月27日在8:08

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

– Marc Dzaebel
18年11月4日在10:37

#3 楼

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

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

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

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

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

@parent:

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

#4 楼

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


请参阅:


https:// primefaces.github.io/primefaces/8_0/#/core/searchexpression