JBoss China's Archiver RichFaces的a4j:region

Larry 发表于 2009-11-3 10:33

RichFaces的<a4j:region>--JSF的局部组件树处理

[i=s] 本帖最后由 Larry 于 2009-11-3 11:25 编辑 [/i]

<a4j:region>标签是最容易让人误解的RichFaces标签之一,但它同时也是RichFaces的最重要的特点之一。有了它,服务器端处理可以仅限于某些指定的组件。
       其中一个原因可能是误解标签名称。许多人认为,该标签是为限制JSF组件树(浏览器)渲染提供的。然而,它是用于相反的目的,标记在应用请求值,处理验证和更新模型值阶段,服务器要对JSF组件树的局部区域做处理。也许“processRegion”将是一个更好的名字,但是我们只需要关注我们现有的。
一个例子:
        假如在一个页面中有5个输入组件。同时假定你只需要服务器处理器中的1到2个,虽然我们无法改变表单提交(所有5个输出值都将提交),我们确可以控制那些组件将在服务器上被处理。组件未在服务器上处理,将无法验证,不会推到模型(在更新模型阶段)。
假设这就是页面[code]<h:form>
     <h:panelGrid>
          <h:inputText id="input1" >
                  <a4j:support event="onblur"/>
          </h:inputText>
          <h:inputText id="input2" >
                  <a4j:support event="onblur"/>
          </h:inputText>
          <h:inputText id="input3" >
                  <a4j:support event="onblur"/>
          </h:inputText>
    </h:panelGrid>
</h:form>[/code]默认情况下,整个页面是一个region。因此,请求发出的任何字段输入都将处理整个表格。
假如我们只想处理input1的值,我们就可以使用a4j:region来实现[code]<h:panelGrid>
   <a4j:region>
      <h:inputText id="input1">
        <a4j:support event="onblur" />
      </h:inputText>
   </a4j:region>
   <h:inputText id="input2">
        <a4j:support event="onblur" />
   </h:inputText>
   <h:inputText id="input3">
        <a4j:support event="onblur" />
   </h:inputText>
</h:panelGrid>[/code]在这种情况下,如果input1触发的提交,虽然整体form依旧被提交,只input1将被服务器处理。
也可以嵌套的写:[code]<h:panelGrid>
   <a4j:region>
        <a4j:region>
   <h:inputText id="input1">
        <a4j:support event="onblur" />
   </h:inputText>
   </a4j:region>
        <h:inputText id="input2">
                <a4j:support event="onblur" />
        </h:inputText>
   </a4j:region>
   <h:inputText id="input3">
        <a4j:support event="onblur" />
   </h:inputText>
</h:panelGrid>[/code]在这个例子中,如果由input1触发的请求提交(输入组件实际上并不触发事件,触发事件的是a4j:support),那么只有当前的区域将被服务器处理。如果input2触发的请求提交,那么input1和input2将同时被服务器处理。如果是input3触发的请求提交,因为它属于整个页面区域,所以整个页面都将被服务器处理。
        当在一个action组件中使用a4j:region,只有该组件的action和为该组件注册的监听器将被服务器处理:[code]<a4j:region>
  <a4j:commandButton action="#{bean.save}" value="Click Me"/>
</a4j:region>[/code]

Larry 发表于 2009-11-3 11:26

[i=s] 本帖最后由 Larry 于 2009-11-3 12:40 编辑 [/i]

a4j:region中的renderRegionOnly属性:
a4j:region有一个重要的属性叫做renderRegionOnly,可以设置为true或者false(false是默认的)。此属性只是限制当前区域的任何重新渲染。让我们看看这个代码片段:[code]<h:panelGrid columns="2">
   <hutputText value="Name:" />
        <h:panelGroup>
                <h:inputText id="name" value="#{bean.name}" required="true"
                         requiredMessage="Name is required"
                         validatorMessage="Must be 3 characters or longer">
                        <a4j:support event="onblur" />
                        <f:validateLength minimum="3" />
                </h:inputText>
                    <rich:message for="name" />
            </h:panelGroup>
        <hutputText value="Age:" />
        <h:panelGroup>
                <h:inputText id="age" value="#{bean.age}" size="4" required="true"
                   requiredMessage="Age is required"
                   validatorMessage="Invalid age">
                     <a4j:support event="onblur" />
                     <f:validateLongRange minimum="0" />
                </h:inputText>
                <rich:message for="age" />
        </h:panelGroup>
</h:panelGrid>[/code]当你从第一个输入区域使用tab切换出去或者点击出去(onblur 事件),没有任何的输入或者输入的不是有效值(如图所示),表单被提交,两块区域都被验证。两块区域都会被处理,因为默认的是全页面是一个region。这并不是我们想要的行为。
[img]http://mkblog.exadel.com/wp-content/uploads/2009/07/regiontag1.png[/img]
如果用户没有机会输入任何东西,我们不希望验证该字段。[code]<h:panelGroup>
   <a4j:region>
        <h:inputText id="name" value="#{bean.name}" required="true"
                requiredMessage="Name is required"
                validatorMessage="Must be 3 characters or longer">
                <a4j:support event="onblur" />
                <f:validateLength minimum="3" />
        </h:inputText>
        <rich:message for="name" />
      </a4j:region>
</h:panelGroup>

<hutputText value="Age:" />
<h:panelGroup>
   <a4j:region>
        <h:inputText id="age" value="#{bean.age}" size="4" required="true"
                requiredMessage="Age is required"
                validatorMessage="Invalid age">
                        <a4j:support event="onblur" />
                        <f:validateLongRange minimum="0" />
        </h:inputText>
        <rich:message for="age" />
   </a4j:region>
</h:panelGroup>[/code]虽然我们解决了这一问题,现在我们又遇到了另外一个问题。
1.将鼠标点击name区域。
2.不输入任何东西(或者输入少于3位字符),离开该区域,将鼠标点击age区域。
3.一个错误提示将出现(只处理了该区域)
[img]http://mkblog.exadel.com/wp-content/uploads/2009/07/regiontag2.png[/img]
4.输入一个负数的年龄,并离开该区域。
5.一个错误提示信息出现在了年龄的后面,但是name后面的错误提示没有了
[img]http://mkblog.exadel.com/wp-content/uploads/2009/07/regiontag3.png[/img] 、
发生了什么?首先,JSF的错误信息是一个request范围的。其次,rich:message 工作原理和 h:message很像,但是组件是始终渲染的,不论这里是否有错误。
那么,这两项是如何相关的?当age输入触发时间时,只有age区域的被处理。name区域的并未做处理,就没有name的错误信息在队列中同时这就是一个新的请求了。因为我们用了rich:message,一个空的字符串值(或者空的错误),在浏览器替代了原来的错误提示信息。
为了帮助我们解决这个问题,我们可以使用renderRegionOnly 属性。
和a4j:region一起,我们设置renderRegionOnly 为true:[code]...
<h:panelGroup>
<a4j:region renderRegionOnly="true">
   <h:inputText id="name" value="#{bean.name}" required="true"
        requiredMessage="Name is required"
        validatorMessage="Must be 3 characters or longer">
        <a4j:support event="onblur" />
        <f:validateLength minimum="3" />
   </h:inputText>
<rich:message for="name" />
</a4j:region>
</h:panelGroup>
...
...
<h:panelGroup>
   <a4j:region renderRegionOnly="true">
        <h:inputText id="age" value="#{bean.age}"
                 size="4" required="true"
                requiredMessage="Age is required"
                validatorMessage="Invalid age">
           <a4j:support event="onblur" />
           <f:validateLongRange minimum="0" />
         </h:inputText>
         <rich:message for="age" />
   </a4j:region>
</h:panelGroup>[/code]
这意味着,任何重新渲染仅限于由该请求被触发的区域。当我们离开age区域而不输入任何东西,name区域的错误提示不会被清理掉,因为我们仅限于更新当前区域(也就是age区域)。
所期望的结果实现了:两条错误信息都显示出来了
[img]http://mkblog.exadel.com/wp-content/uploads/2009/07/regiontag4.png[/img]
有一点要记住,设置renderRegionOnly =“true”不会界定如何重新渲染,它只是限制了更新到当前区域。重新渲染取决于rich:message  
使用renderRegionOnly允许在页面上创造真正的AJAX的区域-即所有的服务器和所有输出输入再加工渲染只局限于这一特定区域。

Larry 发表于 2009-11-3 12:58

[b] [url=http://www.jbosschina.org/redirect.php?goto=findpost&pid=80&ptid=40]2#[/url] [i]Larry[/i] [/b]
使用ajaxSingle属性
一个和region密切相关的属性ajaxSingle。该属性只能应用于一个组件,而a4j:region可以包含任意数量的组件。
[code]<a4j:region>
   <a4j:commandButton action="#{bean.save}" value="Click Me"/>
</a4j:region>

Is the same as:
<pre lang="xml">
<a4j:commandButton action="#{bean.save}" value="Click Me" ajaxSingle="true">[/code]
同时如下
[code]<a4j:region>
    <h:inputText id="age" value="#{bean.city}">
                <a4j:support event="onblur" />
   </h:inputText>
</a4j:region>[/code]
等同于
[code]<h:inputText id="age" value="#{bean.city}">
   <a4j:support event="onblur" ajaxSingle="true"/>
</h:inputText>[/code]

使用process 属性
另一个重要属性就是process 。它可以在所有RichFaces 组件上触发一个AJAX 请求,并可以与ajaxSingle一起使用的组件。当ajaxSingle设置为true,我们知道,只有这部分将被处理。可能会出现一种情况,你还需要处理页面上一些特别的其他的组件。process属性指出了这些需要处理的组件或组件集合。
[code]<h:inputText>
   <a4j:support event="onblur" ajaxSingle="true" process="mobile"/>
</h:inputText>
...
<h:inputText id="mobile"/>[/code]
[i]process[/i] 同样可以指出EL表达式或者组件集合的ID,在这种情况下,该ID下的所有组件都将被处理
[code]<h:inputText>
   <a4j:support event="onblur" ajaxSingle="true"  
                process="infoPanel"/>
</h:inputText>
<h:panelGrid id="infoPanel">
   <h:inputText />
   <h:dataTable>
   ...
   </h:dataTable>
</h:panelGrid>[/code]

[b]总结[/b]
部分组件树处理是在RichFaces的关键概念之一,所以一定要理解。另一个核心概念是局部树呈现和更具体的渲染以前没有呈现的内容。有一点要记住的是,region只在一个AJAX请求方面的工作。region不使用非AJAX请求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值