`
wangqi101023
  • 浏览: 44174 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

Creating a dynamic (AJAX) Column Footer Summary in a Table Component using ADF F

    博客分类:
  • ADF
阅读更多

原文:http://technology.amis.nl/2006/07/27/creating-a-dynamic-ajax-column-footer-summary-in-a-table-component-using-adf-faces/

为了防止打不开,复制原文如下:

 

Creating a dynamic (AJAX) Column Footer Summary in a Table Component using ADF Faces

One fairly common requirement for web applications is the display of Summary fields with calculated values. An obvious example is a table of multiple records with column-summaries appearing underneath the table. Using ADF Faces technology, it is fairly simple to quickly develop an application that presents a multi-record layout based on data retrieved from a database. In this article we will see how we can add a summary column to the columns in such a table layout – and to make those summaries automatically updating when a value for one of the records in the table is changed in the specific column.

 

....
 

Creating the master-detail application

The application I use for this example is a well-known one: a Master-Detail (form-table) page for DEPT and EMP. For each Department, we will see the details in a Form layout with underneath a Table component with all Employees in the Department.

Using JDeveloper 10.1.3, ADF BC, ADF Binding (Framework) and ADF Faces, creating such a page is almost trivial, especially if you generate it using JHeadstart 10.1.3 (which is what I did here). In quick summary the steps:

  1. Create new Application, choose Web Technology (ADF BC and JSF) as Technology Template; Model and ViewController project are created automatically
  2. Create Business Components from Tables EMP and DEPT in SCOTT schema in the Model project; add View Link from Source DeptView to Target EmpView
  3. Using JHeadstart: enable JHeadstart on the ViewController project, create default Application Definition file, generate the application
  4. Without JHeadstart: create a new JSF JSP page, drag and drop DeptView from the AppModule DataControl as Editable Form, drag and drop EmpView2 under DeptView to the jspx page.
  5. Run the Application to verify the data is shown and the master-detail coordination works as expected.

 

Add the Salary Summary to the DeptView ViewObject

We want this page to also contain the summary of all salaries in the currently selected Department. Where to put it is a later concern, let’s first get it on the page in the first place. The steps for this are:

1. Select the DeptView ViewObject and select Edit from the RMB menu

2. On the Attributes tab, press the New button to create a new (transient) attribute called SalSum. SalSum is of type Number, is Never updateable and is not mapped to Column or SQL

3. On the Java Tab, check the checkbox Generate Java File under View Row Class DeptViewRowImpl; also check the Accessors checkbox:

4. Press OK to close the VO Editor wizard.

5. From the RMB menu on the DeptView VO, select the option Goto View Row Class

 

Locate the Number getSalSum() accessor method. Replace the default implementation with this one:

publicNumber getSalSum(){<br />RowIterator emps = getEmpView();
<br />Number sum =newNumber(0);<br />while(emps.hasNext()){<br />      
 sum = sum.add((Number)emps.next().getAttribute(&quot;Sal&quot;));
<br />}<br />return sum;<br />}<br />&nbsp;

6. Add the SalarySum to the page either by dragging and dropping it from the DataControl Palette, or by synchronizing the Dept Group in the JHeadstart Application Definition editor and regenerating the application.

7. Run the application to inspect the newly added SalarySum. It should contain the correct sum of the salaries in the currently selected department. If you change the value of one of the salaries, it will currently not be updated automatically when you leave the field. It will however be synchronized for example when you sort the table by clicking one of the sortable column headers. 

Creating a proper Column Footer with the Salary Summary

The next step is to create the proper layout for the Salary Summary: we want to have it displayed in Footer underneath the Salary Column in our Table Component. The ADF Faces Column Component has a so called footer facet. We can use that facet to specify whatever should be rendered underneath the column. So we can implement the column footer facet for the Salary column, containing the SalarySummary, much like this:

&lt;af:column sortable=&quot;true&quot;
noWrap=&quot;true&quot;<br />    
sortProperty=&quot;Sal&quot; formatType=&quot;number&quot;&gt;<br />
&lt;f:facet name=&quot;header&quot;&gt;<br />&lt;h:panelGroup&gt;
<br />&lt;h:outputText value=&quot;Salary&quot;/&gt;<br />&lt;/h:panelGroup&gt;<br />
&lt;/f:facet&gt;<br />&lt;af:inputText id=&quot;DetailEmpSal&quot; 
value=&quot;#{row.Sal}&quot;<br />               
required=&quot;#{bindings.DetailEmpSal.mandatory}&quot;<br />                 
rows=&quot;#{bindings.DetailEmpSal.displayHeight}&quot;<br />                
columns=&quot;#{bindings.DetailEmpSal.displayWidth}&quot;<br />                
maximumLength=&quot;10&quot;&gt;<br />&lt;f:convertNumber groupingUsed=&quot;false&quot;
<br />                     
pattern=&quot;#{bindings.DetailEmpSal.format}&quot;/&gt;<br />&lt;/af:inputText&gt;<br />
&lt;f:facet name=&quot;footer&quot;&gt;<br />&lt;h:panelGroup&gt;<br />
&lt;af:outputText id=&quot;DeptEmpSalSum&quot;<br />                     
value=&quot;#{bindings.DeptEmpSalSum.inputValue}&quot;&gt;<br />
&lt;f:convertNumber groupingUsed=&quot;false&quot;<br />     
pattern=&quot;#{bindings.DetailEmpSal.format}&quot;/&gt;<br />&lt;/af:outputText&gt;
<br />&lt;/h:panelGroup&gt;<br />&lt;/f:facet&gt;<br />&lt;/af:column&gt;<br />&nbsp;

However, it turns out that the Column Footer Facet gets only rendered if also the Table’s Footer Facet has been specified. Otherwise, the column footer is simply not rendered! The table footer facet is like this:

&lt;f:facet name=&quot;footer&quot;&gt;<br />
&lt;af:outputText id=&quot;deptEmpTableFooter&quot; 
value=&quot;Summary:&quot;/&gt;<br />&lt;/f:facet&gt;<br />&lt;/af:table&gt;<br />&nbsp;

Dynamically Refreshing the Salary Summary whenever a Salary value is changed

At this point, when the page is loaded, the Summary is displayed as expected. However, if we change the value of one of the salaries, the Summary is not immediately updated. Only when the table is refreshed for some other reason, such as sorting or detail disclosure/hide will the new summary value be shown. What we would like to have is an immediate update of the Summary whenever one of the Salaries is changed. We want to leverage the Partial Page Refresh mechanism of ADF Faces to help us realize this.

1. Let’s ensure that a change in a salary value causes an immediate submit to the server. We can easily do that by setting the autoSubmit attribute for the DetailEmpSal inputText component to true:

&lt;af:inputText id=&quot;DetailEmpSal&quot; value=&quot;#{row.Sal}&quot;<br />                 required=&quot;#{bindings.DetailEmpSal.mandatory}&quot;<br />                 rows=&quot;#{bindings.DetailEmpSal.displayHeight}&quot;<br />                 columns=&quot;#{bindings.DetailEmpSal.displayWidth}&quot;<br />                 maximumLength=&quot;10&quot; autoSubmit=&quot;true&quot;&gt;<br />&lt;f:convertNumber groupingUsed=&quot;false&quot;<br />                      pattern=&quot;#{bindings.DetailEmpSal.format}&quot;/&gt;<br />&lt;/af:inputText&gt;<br />&nbsp;

2.  In order to update the SummarySal element upon processing the Partial Page Refresh caused by the Sal
ary change, we have to set the partia
lTriggers attribute.

However, here we run into a problem: we need to specify the ID of the component whose change should trigger the update of the Salary Sum in the partialTriggers attribute for the DeptEmpSalSum component. However, even though the ID for the Salary inputText component seems simple enough – DetailEmpSal – this is not the correct value! Since the Salary field will appear not once but once for every record in our table component and the ID needs to be unique, the actual ID will be different. Each Salary field will have an ID that includes DetailEmpSal as well as :0, :1, :2 etc. to make the ID values unique.

When I try a temporary workaround, just to see whether things are working, I run into a second issue: if I specify partialTriggers="DeptEmpDname" for the Column Footer Facet and/or the Table Footer Facet, it turns out that they are not in fact refreshed when PPR is processed. Only when I specify partialTriggers="DeptEmpDname" at the level of the Table Component will the Footer Facets be properly updated as part of the PPR processing cycle. That means I have now achieved that whenever I change one or more Salary values and I subsequently change the Department Name in the Master record, I get ‘dynamic, instantaneous’ update of the Salary Sum. Almost there, but not quite. By the way: what I am doing here is somewhat similar to Frank Nimphius’ blog article: ADF Faces: Compute totals of selected rows in a multi select table. He does not seem to have a problem with Table Footer refresh so perhaps I am doing something wrong here.

After consulting Frank and Duncan Mills, I am pointed in a new direction: programmatically specifying the targets of Partial Page Refresh. Sounds interesting, let’s try it out:

Programmatically specifying the targets of Partial Page Refresh

There is an API call – AdfFacesContext.getCurrentInstance().addPartialTarget(<the component to
refresh>); – that Duncan suggested to me. This should allow me to specify the Table – or perhaps even the Table and/or Column Footer Facet – that should be refreshed as part of the current PPR cycle. Of course, this call should be made whenever Salary has been changed. So using a ValueChangeListener, I should be well on my way. Should I not?

1. Create a new class EmpMgr to handle the Salary Changed event by adding the EmployeeTable to the list of partial targets:

import javax.faces.application.Application;<br />
import javax.faces.component.UIComponent;<br />
import javax.faces.context.FacesContext;<br />
import javax.faces.event.ValueChangeEvent;<br /><br />
import oracle.adf.view.faces.context.AdfFacesContext;<br /><br />
publicclassEmpMgr{<br />publicEmpMgr(){<br />}<br /><br />
publicvoidHandleSalaryChangeEvent(ValueChangeEvent valueChangeEvent)
{<br />Application app =FacesContext.getCurrentInstance().getApplication();
<br />UIComponent table =(UIComponent)app.createValueBinding(
&quot;#{DetailEmpCollectionModel.table}&quot;).getValue(FacesContext.getCurrentInstance());
<br />AdfFacesContext.getCurrentInstance().addPartialTarget(table);<br /><br />}<br />}
<br />&nbsp;

Note: the table component had its Binding property already set to #{DetailEmpCollectionModel.table}; I am simply reusing that binding. Also note that trying to use the DeptEmpSalSum outputText as partialTarget did not lead to a refresh: I had to use the table as refresh target.

2. Configure this new class as Managed Bean 

...<br />&lt;managed-bean&gt;<br />&lt;managed-bean-name&gt;EmpMgr&lt;
/managed-bean-name&gt;<br />&lt;managed-bean-class&gt;EmpMgr&lt;
/managed-bean-class&gt;<br />&lt;managed-bean-scope&gt;session&lt;
/managed-bean-scope&gt;<br />&lt;/managed-bean&gt;<br />&lt;/faces-config&gt;<br />&nbsp;

3. Specify a ValueChangeListener for the Salary field in my Employees table:

&lt;af:inputText id=&quot;DetailEmpSal&quot; value=&quot;#{row.Sal}&quot;<br />                 required=&quot;#{bindings.DetailEmpSal.mandatory}&quot;<br />                 rows=&quot;#{bindings.DetailEmpSal.displayHeight}&quot;<br />                 columns=&quot;#{bindings.DetailEmpSal.displayWidth}&quot;<br />                 maximumLength=&quot;10&quot; autoSubmit=&quot;true&quot;<br />    valueChangeListener=&quot;#{EmpMgr.HandleSalaryChangeEvent}&quot;&gt;<br />&lt;f:convertNumber groupingUsed=&quot;false&quot;<br />                   pattern=&quot;#{bindings.DetailEmpSal.format}&quot;/&gt;<br />&lt;/af:inputText&gt;<br />&nbsp;<br />

4. Run the application, change a salary and keep your fingers crossed… IT WORKS!!!! (Thanks Frank and Duncan). Note: this opens up a lot of very interesting possibilities: we can determine dynamically on the server side which fields to be updated in the browser by simply adding them to the list of partialTargets.

分享到:
评论

相关推荐

    ADF实现多选框及分页

    本文将详细解析如何在ADF中实现多选框功能和分页效果,特别是针对Table组件的运用。 首先,让我们了解什么是ADF。Oracle ADF 是一个Java EE框架,它提供了一整套工具和服务,用于构建企业级Web应用。ADF包含模型、...

    ADF检验MATLAB程序.zip_ADF单位根检验_ADF检测_MATLAB adf_adftest matlab_adf检验

    标题中的“ADF检验MATLAB程序.zip”指的是一个包含MATLAB代码的压缩文件,用于执行Augmented Dickey-Fuller(ADF)单位根检验。ADF检验是统计学中一种常用的方法,用于判断时间序列数据是否具有单位根,即数据是否...

    宽带PLL ADF41513(1)_ADF_acceptwcc_adf4360_ADF41513_ADf4360-7_

    标题中的“宽带PLL ADF41513(1)_ADF_acceptwcc_adf4360_ADF41513_ADf4360-7_”提及了两个关键器件:ADF41513和ADF4360-7。这两个都是高性能的频率合成器,在无线通信、测试设备以及各种信号处理应用中广泛使用。 ...

    ADF4351配置程序.zip_ADF4351_ADF4351程式_adf4350配置_adf4351 程序_adf4351配置

    **ADF4351配置程序** ADF4351是一款高性能、高精度的频率合成器,广泛应用于无线通信、测试设备、卫星接收等系统中。它具有宽范围的频率输出能力,可编程的分频器和倍频器设计,使得在不同应用中能够灵活调整输出...

    递归实现的 ADF Dynamic tree

    本文将深入探讨如何使用递归实现ADF(Attribute Dependency Framework)动态树。ADF动态树是一种数据结构,它能够根据特定规则自动生成或调整树状结构,常用于数据建模、图形用户界面设计或解析复杂数据结构。 首先...

    ADF4351源码(STM32F103+STM32F407)支持函数调用更改频率

    标题中的“ADF4351源码(STM32F103+STM32F407)支持函数调用更改频率”指的是一个电子竞赛项目中使用的源代码,主要针对ADF4351锁相环(PLL)芯片,该芯片能够产生精确可调的射频信号。这个源代码兼容两种STM32微...

    building_java_applications_using_the_arcgis_server_web_adf_and_ajax

    ### 构建基于ArcGIS Server Web ADF与Ajax的Java应用程序 #### 一、课程概述与目标 在本次由ESRI Developer Summit 2008提供的培训课程中,主题为“构建基于ArcGIS Server Web ADF与Ajax的Java应用程序”,旨在...

    ADF下拉框傻瓜教程

    ### ADF 下拉框傻瓜教程 #### 一、引言 在软件开发过程中,下拉列表(List of Values, LOV)是非常常见且实用的功能组件之一,它可以帮助用户快速选择预定义的数据项,提高用户体验并减少数据输入错误。本教程将...

    ADF界面使用多皮肤 ADF刷新界面方法

    **ADF(Application Development Framework)** 是Oracle公司推出的一款基于Java EE平台的企业级开发框架,它为企业构建富客户端和Web应用程序提供了强大的支持。ADF利用模型-视图-控制器(MVC)设计模式,简化了...

    ADF table中使用selectbooleancheckbox组件

    在Oracle Application Development Framework (ADF) 中,`SelectBooleanCheckbox` 是一个非常有用的组件,它用于在表(Table)中展示可选的布尔值。在Web应用程序中,这种组件通常用于让用户选择一组选项中的某一项...

    ADF4351.rar_ADF4351_ADF4351锁相环例程_adf4351双路输出_adf4351辅助输出

    **ADF4351简介** ADF4351是一款高性能的射频(RF)频率合成器,由ADI公司设计生产,适用于多种无线通信系统。它采用先进的锁相环(PLL)技术,能够产生精确且可调的射频信号,频率范围广泛,正如描述中所提及的,...

    adf JDeveloper 相关文档

    ADF 主要包含三个部分:**ADF Business Components**、**ADF Task Flows** 和 **ADF Faces**。 1. **ADF Business Components**: 这是用于构建业务逻辑层的组件集合。它支持 Java Persistence API (JPA),使开发者...

    ADF实现多选框及分页的Table组件

    在Oracle Application Development Framework (ADF) 中,`af:table`组件是用于展示和操作数据集的强大工具,提供了诸如排序、过滤、列切换等丰富的功能。然而,有些用户可能更倾向于使用多选框来选择表格中的行,...

    ADF Table popup弹出编辑和添加

    在Oracle Application Development Framework (ADF) 中,`ADF Table` 是一个强大的组件,用于展示和管理数据。本示例主要探讨如何实现"ADF Table popup 弹出编辑和添加"功能,这是在开发企业级Web应用程序时非常常见...

    基于MSP430F5438A的ADF4351程序

    《基于MSP430F5438A的ADF4351程序解析》 在现代电子系统中,频率源扮演着至关重要的角色。精确、稳定的频率源能够确保系统的正常运行,尤其是在通信、测试测量等领域。本篇将深入探讨一个基于MSP430F5438A微控制器...

    Jdeveloper 10g J2EE Student Guide PPT

    12 Using ADF Faces Components 13 Applying Standards to the Application 14 Building a Query Page with UI Components 15 Creating Updatable Pages 16 Handling Application Events 17 Creating the Business ...

    adf4159.rar_FMCW_adf4159

    标题中的“adf4159.rar_FMCW_adf4159”表明这是一个与ADF4159芯片相关的资源包,重点在于FMCW(Frequency Modulated Continuous Wave)技术的应用。FMCW雷达是一种利用连续波频率调制来测量目标距离、速度和角度的...

    verilog配置ADF4355

    在数字信号处理领域,ADF4355是一款高性能的射频频率合成器,常用于通信系统、测试设备以及各种无线应用。它提供了宽广的频率范围、高精度和灵活的编程能力。本教程将深入探讨如何使用硬件描述语言Verilog对ADF4355...

    ArcGIS Server .Net ADF中的AJAX.rar

    《ArcGIS Server .Net ADF中的AJAX技术详解》 ArcGIS Server是Esri公司推出的一款强大的地理信息系统(GIS)服务器产品,它提供了丰富的服务端功能,用于处理、存储和分发地理空间数据。在ArcGIS Server的开发过程...

Global site tag (gtag.js) - Google Analytics