了解 PrimeFaces 流程/更新和 JSF f:ajax 执行/渲染属性 [英] Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes

查看:28
本文介绍了了解 PrimeFaces 流程/更新和 JSF f:ajax 执行/渲染属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

What exactly are process and update in PrimeFaces p:commandXxx components and execute and render in f:ajax tag?

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

Which works at the time of validation? What does update attribute do rather than updating value to component from back end? Do process attribute bind value to model? What exactly do @this, @parent, @all and @form in both attributes?

下面的例子工作正常,但我对基本概念有点困惑.

The example below is working fine, but I am a little confused in basic concepts.

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

推荐答案

<f:ajax 执行>

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

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

The process attribute is server side and can only affect UIComponents implementing EditableValueHolder (input fields) or ActionSource (command fields). The process attribute tells JSF, using a space-separated list of client IDs, which components exactly must be processed through the entire JSF lifecycle upon (partial) form submit.

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

JSF will then apply the request values (finding HTTP request parameter based on component's own client ID and then either setting it as submitted value in case of EditableValueHolder components or queueing a new ActionEvent in case of ActionSource components), perform conversion, validation and updating the model values (EditableValueHolder components only) and finally invoke the queued ActionEvent (ActionSource components only). JSF will skip processing of all other components which are not covered by process attribute. Also, components whose rendered attribute evaluates to false during apply request values phase will also be skipped as part of safeguard against tampered requests.

请注意,对于 ActionSource 组件(例如 )非常重要,您还必须将组件本身包含在 过程中 属性,特别是如果您打算调用与组件关联的操作.因此,下面的示例旨在在调用某个命令组件时仅处理某些输入组件是行不通的:

Note that it's in case of ActionSource components (such as <p:commandButton>) very important that you also include the component itself in the process attribute, particularly if you intend to invoke the action associated with the component. So the below example which intends to process only certain input component(s) when a certain command component is invoked ain't gonna work:

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

它只会处理#{bean.foo}不会#{bean.action}.您还需要包含命令组件本身:

It would only process the #{bean.foo} and not the #{bean.action}. You'd need to include the command component itself as well:

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

或者,正如您显然发现的那样,如果 @parent 碰巧是唯一具有公共父级的组件:

Or, as you apparently found out, using @parent if they happen to be the only components having a common 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:

Or, if they both happen to be the only components of the parent UIForm component, then you can also use @form:

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

如果表单包含更多您想在处理过程中跳过的输入组件,这有时是不可取的,在您想根据当前更新另一个输入组件或某些 UI 部分的情况下,这通常是不可取的ajax 侦听器方法中的输入组件.您不希望其他输入组件上的验证错误阻止了 ajax 侦听器方法的执行.

This is sometimes undesirable if the form contains more input components which you'd like to skip in processing, more than often in cases when you'd like to update another input component(s) or some UI section based on the current input component in an ajax listener method. You namely don't want that validation errors on other input components are preventing the ajax listener method from being executed.

然后是 @all.这对 process 属性没有特殊影响,但仅在 update 属性中有效.process=@all" 的行为与 process=@form" 完全相同.无论如何,HTML 不支持一次提交多个表单.

Then there's the @all. This has no special effect in process attribute, but only in update attribute. A process="@all" behaves exactly the same as process="@form". HTML doesn't support submitting multiple forms at once anyway.

顺便说一下,还有一个 @none,如果您绝对不需要处理任何事情,但 想通过以下方式更新某些特定部分,它可能很有用update,尤其是那些内容不依赖于提交的值或动作侦听器的部分.

There's by the way also a @none which may be useful in case you absolutely don't need to process anything, but only want to update some specific parts via update, particularly those sections whose content doesn't depend on submitted values or action listeners.

应该注意的是,process 属性对 HTTP 请求负载(请求参数的数量)没有影响.意思是,发送所有内容"的默认 HTML 行为. 的 HTML 表示中包含的内容将不受影响.如果您的表单很大,并且希望将 HTTP 请求负载减少到处理中绝对必要的那些,即只有 process 属性覆盖的那些,那么您可以设置 partialSubmit 属性,如 .您还可以通过编辑 web.xml 并添加

Noted should be that the process attribute has no influence on the HTTP request payload (the amount of request parameters). Meaning, the default HTML behavior of sending "everything" contained within the HTML representation of the <h:form> will be not be affected. In case you have a large form, and want to reduce the HTTP request payload to only these absolutely necessary in processing, i.e. only these covered by process attribute, then you can set the partialSubmit attribute in PrimeFaces Ajax components as in <p:commandXxx ... partialSubmit="true"> or <p:ajax ... partialSubmit="true">. You can also configure this 'globally' by editing web.xml and add

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

或者,您也可以使用 OmniFaces 3.0+ 的默认行为.

Alternatively, you can also use <o:form> of OmniFaces 3.0+ which defaults to this behavior.

与 PrimeFaces 特定的 process 等效的标准 JSF 是 execute 来自 .它的行为完全相同,除了它不支持逗号分隔的字符串,而 PrimeFaces 支持(尽管我个人建议只坚持空格分隔的约定),也不支持 @parent 关键字.此外,了解 默认为 @form 默认为 @this.最后,了解 process 支持所谓的PrimeFaces Selectors"也很有用,另见 如何在 update="@(.myClass)" 中使用 PrimeFaces Selectors工作吗?

The standard JSF equivalent to the PrimeFaces specific process is execute from <f:ajax execute>. It behaves exactly the same except that it doesn't support a comma-separated string while the PrimeFaces one does (although I personally recommend to just stick to space-separated convention), nor the @parent keyword. Also, it may be useful to know that <p:commandXxx process> defaults to @form while <p:ajax process> and <f:ajax execute> defaults to @this. Finally, it's also useful to know that process supports the so-called "PrimeFaces Selectors", see also How do PrimeFaces Selectors as in update="@(.myClass)" work?

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

The update attribute is client side and can affect the HTML representation of all UIComponents. The update attribute tells JavaScript (the one responsible for handling the ajax request/response), using a space-separated list of client IDs, which parts in the HTML DOM tree need to be updated as response to the form submit.

JSF 然后会为此准备正确的 ajax 响应,包含需要更新的部分.JSF 将跳过 ajax 响应中 update 属性未涵盖的所有其他组件,从而保持响应负载较小.此外,在渲染响应阶段 rendered 属性评估为 false 的组件将被跳过.请注意,即使它会返回 true,如果它最初是 false,JavaScript 也无法在 HTML DOM 树中更新它.你需要包装它或更新它的父级.另请参阅Ajax 更新/渲染不适用于具有渲染属性的组件.

JSF will then prepare the right ajax response for that, containing only the requested parts to update. JSF will skip all other components which are not covered by update attribute in the ajax response, hereby keeping the response payload small. Also, components whose rendered attribute evaluates to false during render response phase will be skipped. Note that even though it would return true, JavaScript cannot update it in the HTML DOM tree if it was initially false. You'd need to wrap it or update its parent instead. See also Ajax update/render does not work on a component which has rendered attribute.

通常,您希望更新真正需要刷新"的组件;在客户端(部分)表单提交时.下面的示例通过 @form 更新整个父表单:

Usually, you'd like to update only the components which really need to be "refreshed" in the client side upon (partial) form submit. The example below updates the entire parent form via @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)

(note that process attribute is omitted as that defaults to @form already)

虽然这可能工作正常,但在此特定示例中不需要更新输入和命令组件.除非您在 action 方法中更改模型值 foobar(这反过来在 UX 的角度来看是不直观的),否则没有更新的意义他们.消息组件是唯一真正需要更新的:

Whilst that may work fine, the update of input and command components is in this particular example unnecessary. Unless you change the model values foo and bar inside action method (which would in turn be unintuitive in UX perspective), there's no point of updating them. The message components are the only which really need to be updated:

<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 样式类,因此还应该执行以下操作:

However, that gets tedious when you have many of them. That's one of the reasons why PrimeFaces Selectors exist. Those message components have in the generated HTML output a common style class of ui-message, so the following should also do:

<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 选择器如何工作?详情)

(note that you should keep the IDs on message components, otherwise @(...) won't work! Again, see How do PrimeFaces Selectors as in update="@(.myClass)" work? for detail)

@parent 只更新父组件,从而覆盖当前组件和所有兄弟组件及其子组件.如果您已将表单分成各自负责的正常组,这将更有用.@this 显然只更新当前组件.通常,仅当您需要在 action 方法中更改组件自己的 HTML 属性之一时才需要这样做.例如

The @parent updates only the parent component, which thus covers the current component and all siblings and their children. This is more useful if you have separated the form in sane groups with each its own responsibility. The @this updates, obviously, only the current component. Normally, this is only necessary when you need to change one of the component's own HTML attributes in the action method. E.g.

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

想象一下 oncomplete 需要与 action 中改变的 value 一起工作,如果组件未更新,原因很简单,oncomplete 是生成的 HTML 输出的一部分(因此其中的所有 EL 表达式都在渲染响应期间进行评估).

Imagine that the oncomplete needs to work with the value which is changed in action, then this construct wouldn't have worked if the component isn't updated, for the simple reason that oncomplete is part of generated HTML output (and thus all EL expressions in there are evaluated during render response).

@all 更新整个文档,应谨慎使用.通常,您希望通过普通链接()或重定向来对此使用真正的 GET 请求-after-POST 通过 ?faces-redirect=trueExternalContext#redirect().实际上,process=@form"update="@all" 与非 ajax(非部分)提交具有完全相同的效果.在我的整个 JSF 职业生涯中,我遇到的 @all 唯一明智的用例是显示整个错误页面,以防在 ajax 请求期间发生异常.另见 处理 AJAXified 组件的 JSF 2.0 异常的正确方法是什么?

The @all updates the entire document, which should be used with care. Normally, you'd like to use a true GET request for this instead by either a plain link (<a> or <h:link>) or a redirect-after-POST by ?faces-redirect=true or ExternalContext#redirect(). In effects, process="@form" update="@all" has exactly the same effect as a non-ajax (non-partial) submit. In my entire JSF career, the only sensible use case I encountered for @all is to display an error page in its entirety in case an exception occurs during an ajax request. See also What is the correct way to deal with JSF 2.0 exceptions for AJAXified components?

与 PrimeFaces 特定的 update 等效的标准 JSF 是 render 来自 .它的行为完全相同,除了它不支持逗号分隔的字符串,而 PrimeFaces 支持(尽管我个人建议只坚持空格分隔的约定),也不支持 @parent 关键字.updaterender 默认为 @none(即无").

The standard JSF equivalent to the PrimeFaces specific update is render from <f:ajax render>. It behaves exactly the same except that it doesn't support a comma-separated string while the PrimeFaces one does (although I personally recommend to just stick to space-separated convention), nor the @parent keyword. Both update and render defaults to @none (which is, "nothing").

另见:

这篇关于了解 PrimeFaces 流程/更新和 JSF f:ajax 执行/渲染属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆