内容


使用 Rational Business Developer 基于 EGL 构建 JSF 搜索页面

创建两种允许用户以不同方式搜索数据库的页面

Comments

在开始之前

了解您想从本文中学到什么,以及怎样去获得这些知识。

关于本文

通过教您学习更多关于 IBM® Rational® Business Developer 的组件,Enterprise Generation Language (EGL)以及 Java™Server Faces(JSF)的高级应用,本篇教程扩展了教程“Hello World: Rational Business Developer Extension —— 数据访问和 Web 应用程序:在不了解 Java 语言的情况下创建一个 Java Web 应用程序”的内容。在本教程中,您将创建两种允许用户以不同方式搜索数据库的页面。

这些页面接受用户的输入,并搜索数据库中与输入相匹配的记录,并在同一页面中显示出结果。这并不是创建一个搜索页面唯一的,或者最佳的方式,但是这种方式能够解释一些重要的 EGL 以及 JSF 概念。

本篇教程将要创建的搜索页面,不同于 Web 搜索引擎,也不同于搜索 Internet 或者单个 Web 站点的页面。范例中您将创建的搜索页面,搜索的是数据库数据,而不是 Web 页面,或者 Web 页面上的信息。

目标

在本教程中,您将学习完成以下任务:

  • 使用 SQL 语言来筛选结果得到的搜索页面
  • 创建一个通用的 EGL 记录部分,并在页面中显示出来
  • 应用一个带动态数据的组合框
  • 对输入控件应用预输入(type-ahead) 支持
  • 更新部分基于一次 Ajax 请求的页面

时间要求

本篇教程大概需要 90 分钟左右来完成学习,如果您还需查阅与本文相关的其他内容,那么所花的时间将会更多。

前提条件

在您开始学习本文以前,您必须已经完成教程“Hello World: Rational Business Developer Extension —— 数据访问和 Web 应用程序:在不了解 Java 语言的情况下创建一个 Java Web 应用程序”的学习。

教程应用程序

当您完成本文的学习后,您将会创建一个搜索页面,该页面能够接受用户的输入,并与数据库中的数据相比较,然后向用户返回查询的结果。您将会创建一个同时使用两种参数的搜索(一次AND 搜索)。您还可以将那个搜索改为使用两个参数中的一种 (一次OR 搜索)。并且您将在页面上设置一个 radio 按钮组,以允许用户在两种模式中选择一个。

通过在页面上放置一个组合框,您可以限制用户对搜索参数的选择:组合框将向用户提供一组固定的选择,而不是任由他们直接输入一串字符 。最后,您还将学到,怎样加工得到的搜索结果,组合区域,以及决定怎样在页面中将输出显示出来。

第一个完成的搜索页面,外观如图 1 所示。

图1. 首先得到的搜索页面
带有区域与结果的标签
带有区域与结果的标签

您将创建的第二个搜索页面,会展示出 Ajax 功能与 EGL 的简单应用。Ajax 的一个普遍应用,是向用户输入提供建议,以当作 type-ahead 支持。以这种方式,页面在数据库中搜索,查找与用户在输入区输入内容相似的项目,如图 2 所示。

图 2. Ajax type-ahead 支持
显示以 s 开头的种类,及记录
显示以 s 开头的种类,及记录

一旦用户接受了建议中的一种,页面将在不重新加载的前提下,使用另一个 Ajax 请求,以向用户显示数据库信息:

图 3. 显示所接受建议的细节
包括 ID,姓名,以及电话号码的搜索结果
包括 ID,姓名,以及电话号码的搜索结果

第 1 讲:创建一个简单的搜索页面

在本讲中,您将要建立一个简单的搜索页面。在下面的步骤里,您要向该页面添加 EGL 代码,以使该页面能工作。

建立该页面的基本步骤,与建立其他任何 EGL-JSF Web 页面步骤基本相同:

  1. 创建 Web 页面。
  2. 创建 EGL 变量。
  3. 将 EGL 数据与 JSF 组件联系起来。
  4. 添加 EGL 功能,以管理 EGL 变量。

本讲涉及到上面提到的前三步,下一分讲涉及到第四步。

创建 Web 页面

完成以下步骤。

  1. 在 Project Explorer 视图中,点击 EGLWeb 项目的 WebContent 文件夹以选中它。
  2. 点击 File>New>Other
  3. 在 New 窗口中,展开 Web 并点击 Web page
  4. 点击 Next 。New Web Page 窗口将会打开。
  5. File Name 区域,输入customersearch.jsp 以作为新文件的名字,包括扩展。
  6. 确定 Folder 区域显示的是 /EGLWeb/WebContent 文件夹。
  7. Template 列表中,点击 My Templates
  8. Preview 框中,点击 A_gray.htpl 模板。
  9. 点击 Finish。新页面将会在编辑器中创建并打开。
  10. 输入Customer Search,以替换掉默认值。
  11. 按下 Enter 键三次,以插入三条空白行。

创建记录

在这些步骤中,您创建两个 EGL 记录。searchTerms 记录搜索输入,或者搜索项。在这种情况下,searchTerms 记录记载了用户搜索的名字以及状态。searchResults[]记录阵列代表了搜索结果,或者数据库中与搜索输入相匹配的记录。

  1. 从 Palette 视图的 EGL 折叠项中,拖拉 New Variable 到页面中,它位于 Customer Search 文本之下。 打开 Create a New EGL Data Variable 窗口。
  2. Type Selection 之下,点击 Record
  3. Record Type 之下,点击 Customer
  4. 对于 Enter the name of the field,输入searchTerms
  5. 清除 Array 复选框选择。
  6. 清除 Add controls to display the EGL element on the Web page 复选框选择。
  7. 点击 OK
  8. 从 Palette 视图中拖拉另一个 New Variable 到页面中,它位于 Customer Search 之下。再次打开 Create a New EGL Data Variable 窗口。
  9. Type Selection 之下,点击 Record
  10. Record Type 之下,点击 Customer
  11. Enter the name of the field 之下,为该区域输入searchResults
  12. 选中 Array 复选框。
  13. 清除 Add controls to display the EGL element on the Web page 复选框选择。
  14. 点击 OK

现在两个新变量(searchTerms 以及searchResults )在 Page Data 视图中显示出来。

向页面添加记录

完成以下步骤:

  1. 在 Page Data 视图下,展开 JSF Handler
  2. 在 Page Data 视图中,拖拉 searchTerms - Customer 记录到页面中,在 Customer Search 文本下。打开 Insert Control 窗口。
  3. 在 Insert Control 窗口中,在 Create controls for 之下,点击 Updating an existing record
  4. Fields to display 之下,点击 None。这将清除掉所有复选框的选择。
  5. 选中 LastName 以及 State 区域旁边的复选框。
  6. 点击 Options 按钮。
  7. 在 Options 窗口中,选中 Submit button 复选框。.
  8. Submit button Label 区域,输入Submit
  9. 清除 Delete button 复选框。
  10. 点击 OK
  11. 点击 Finish。一个带有用户最终姓名以及状态的表格,将会在页面中显示出来。您可以在这些输入区中,输入您的搜索项以搜索一个用户。页面看起来如图 4 所示。
图 4. 通过最终名字及状态搜索
带有搜索区域,提交按钮,以及出错信息的界面
带有搜索区域,提交按钮,以及出错信息的界面
  1. 通过将鼠标光标置于 Submit 按钮的{Error Messages}区域右边,并点击 Enter 键,可在 Submit 按钮的下边添加一个空白行。
  2. 在 Palette 视图下,打开 Enhanced Faces Components 折叠项。
  3. Enhanced Faces Components 折叠项中拖拉两个 Output 组件到页面中,即 Submit 按钮下面的新行上。该输出区域将显示出返回结果的数量以及一条信息,如列表 1 所示。
列表 1. 结果信息
5 Customer(s) found. Search again?
  1. 在 Page Data 视图中,拖拉页面中的 searchResults - Customer[] Submit 按钮以及两个新输出区域之下。打开 Insert List Control 窗口。
  2. 在 Insert List Control 窗口中,点击 Displaying an existing record (read-only)附近的 radio 按钮。
  3. Columns to display 下面,点击列表下的 None 按钮。这将清除掉所有复选框的选择。
  4. 选中 LastNameEmailAddress 以及 State 区域旁边的复选框。Insert List Control 窗口外观如图 5 所示。
图5. 指定显示的列以及怎样去显示它们
选择指定选项的窗口
选择指定选项的窗口
  1. 点击 Finish
  2. 保存页面。


现在搜索页面已经有了用户键入搜索项的输入区域,以及用于显示搜索结果的数据表。搜索页面如图 6 所示。

图 6. 带有输出列的搜索页面
名,email 地址,以及状态列
名,email 地址,以及状态列

分讲总结

现在您已创建了一个简单的搜索页面,您学习了如何完成以下事项:

  • 创建一个 EGL Web 页面
  • 创建 EGL 记录
  • 向 Web 页面添加 EGL 记录


现在您已经为添加代码,完成搜索功能做好准备。

第 2 讲: 为搜索功能添加代码

既然现在已经创建了 Web 页面,您必须添加,能接受 Web 页面搜索项的 EGL 代码,以根据这些搜索项搜索数据库 ,并在页面中显示出搜索结果。

因为这些搜索功能很复杂,您可以创建一个列表库以管理它们。然后,您可以再使用这些搜索功能,并保持您的 JSF Handlers 尽量简单。

  1. 右击您的 EGLWeb 项目的 EGLSource 文件夹,并点击 New > Library。打开 New EGL Library 窗口。
  2. EGL source file name 区域,输入SearchLibrary 以作为新列表库的名字。
  3. Package 区域,输入libraries。如果您还没有这个名字的包裹, EGL 将会创建一个新的。
  4. EGL Library Type 之下,点击 Basic
  5. 点击 Finish。新列表库被创建并在 EGL 编辑器中被打开。
  6. 删除新列表库中所有的文本,这样所有剩下的如列表 2 所示。
列表 2. 指定包库
package libraries;
               
library SearchLibrary type BasicLibrary
   
end

现在您可以向该列表库添加功能,并在您的 JSF Handlers 中使用它们。

  1. 在 SearchLibrary 文件的末尾,最终 End 申明的前面,插入如列表 3 所示的代码 。
列表 3. 搜索输入变量
function NameAndStateSearch_And(lname string in, 
  state char(2) in, 
  customer Customer[])
  get customer;
end
  1. 该功能与从数据库中获得每项记录的其他列表库的功能相似。不同点是,该功能获得以下三个参数:
    • 字符串变量lname,其值代表要搜索用户的最终名字。
    • 状态变量state ,其值代表要搜索用户的状态。
    • 用户记录的customer 数组,它记录下搜索的结果。


    现在,该功能将获得数据库中的每一项记录。在接下来的几步中,您将要编辑该功能产生的 SQL 申明,这样,只有那些匹配搜索项lname 以及state 的记录会被返回。
  2. 如果您没有使用完成的代码,以插入该功能,向列表添加如下的import 申明,直接位于package libraries; 行以下:
列表 4. Import 申明
import eglderbyr7.data.Customer;
  1. 右击get customer 行中的词 customer,然后点击 SQL Statement > Add。您必须将鼠标光标置于词customer 之上,以便能够编辑 SQL 申明。向代码行get customer 添加清楚的 SQL 申明。

    严格来说,您的代码毫无变化。EGL 仅仅是展示出遇到get customer 代码时,将会用到的默认 SQL 代码 。既然现在页面中已清晰显示出了 SQL 代码,您可以编辑它,从而改变get customer 申明。在这种情况下,您想把申明,由获得所有用户的记录,改为只获得匹配最后名字及状态的用户记录。
  2. 通过将鼠标光标置于行的末尾,并点击 Enter 键,在from EGL.CUSTOMER 行的末尾,添加一个空白行。
  3. from EGL.CUSTOMER 之下的新空白行中,插入如图 5 所示的代码。
列表 5. Where 状况
where EGL.CUSTOMER.LAST_NAME like :lname 
  and EGL.CUSTOMER."STATE" = :state
  1. 代码(egl_code02-01-02a,您可以下载它) 看起来如图 7 所示。
图 7. SQL 选择申明
SQL 选择申明
SQL 选择申明
  1. 您添加的代码不是 EGL,而是 SQL。 代码EGL.CUSTOMER.LAST_NAME 是您项目使用的范例数据库某个区域的完整名字。如果您查看 eglderbyr7.data 中的 Record 部分,您将看到同样参考该区域的记录(例如 Customer 记录)。代码:lname :state 被称作主变量,在本例中,它是您使用的 SQL 代码中的 EGL 变量。STATE 带上引号是为了说明,“STATE”是表格的名字,而不是 SQL 的 保留词。
  2. EGL 提供创建和生成 SQL 申明的不同方式。在早期的 EGL 系列中,通过指定一个特定的用户 ID 号,您可以获得一个特定的数据库记录。 该条创建的 SQLwhere 申明,与您刚刚添加的where 申明相似。您也可以使用defaultSelectCondition 来达到相同的效果。
  3. 保存文件。
  4. 通过点击 Ctrl+G 键,或者在编辑器页面的内容区域右击,然后点击 Generate,生成列表库。

这里有列表库文件完整的代码(egl_code02-01-02a.html,文件的压缩包可以通过教程的 下载 部分获得)。如果在文件中看到以红色 X 符号标记的出错地方,确认您的代码匹配 egl_code02-01-02a.html 文件中的代码 。

完成以下步骤:

  1. 打开customersearch.jsp 页面。
  2. 在编辑器页面的内容区域右击,并选择 Edit Page Code。打开页面代码文件。
  3. 在页面customersearch.jsp 的 JSF Handler 中,找到您所创建的,用于表示搜索项以及搜索结果的变量,如列表 6 所示。
列表 6. 搜索变量
searchResults Customer[0];
searchTerms Customer;
  1. 在前面创建变量之后,添加如列表 7 所示的代码,以创建两个附加变量(resultMessage 以及 numberOfResults )。
列表 7. 创建两个变量
resultMessage char(80);
numberOfResults int;
  1. 接下来,您需要创建一个 Web 页面的函数。该函数将向列表库中的函数传递searchResults 变量以及searchTerms 所需的区域。
  2. 向 JSF Handler 添加如列表 8 所示的函数。
列表 8. 搜索函数
function searchFunction()
  searchTerms.LastName = searchTerms.LastName::"%";
  SearchLibrary.NameAndStateSearch_And(
    searchTerms.LastName, 
    searchTerms.State, searchResults);
  resultMessage = " customer(s) found.";
  numberOfResults = searchResults.getSize();
end
  1. 如果您没有使用完成代码插入函数,在package jsfhandlers行的下面,添加如列表 9 所示的import申明:
列表 9. 添加引入申明
import libraries.SearchLibrary;
  1. 最后,您需要向onPreRender()函数添加代码,以便在一次搜索失败以后,重新打开页面。
  2. 向 JSF Handler 添加如列表 10 所示的函数:
列表 10.如果没有搜索结果的信息
function onPreRender()
  if (searchResults.getSize() == 0)
    resultMessage = "No customers found or no search criteria entered.";
  end
end
  1. 向 JSF Handler 添加onPreRenderFunction 属性,这样申明看起来如列表 11 所示的代码一样 :
列表 11. 添加 onPreRenderFunction
handler customersearch type JSFHandler
    {onConstructionFunction = onConstruction,
     onPreRenderFunction = onPreRender,
     view = "customersearch.jsp"}
  1. 下面是您刚刚添加的页面代码中,一些需要注意的技术点:
    1. 记录searchTerms 以及记录数组searchResults,都是 Customer 记录的例子中的一种。您也可以创建 Record 或者 DataItem 部分的多种例子。
    2. 该代码包含了 searchFunction() 函数, EGL 用它来传递页面的按钮。该函数访问本讲中,您在前面向列表库添加的 NameAndStateSearch_And()函数。
    3. 搜索函数会在用户输入名字的末尾,添加一个随机字符。例如,如果用户输入Sm,那么搜索字符串将会变为Sm%,并返回诸如Smith Smiley 之类的结果。
    4. 搜索函数是 case-sensitive。
  2. 保存并生成文件。该文件(egl_code02-01-02b.html,文件的压缩包可以通过教程的 下载 部分获得)看起来如图 8 所示。
图 8. 修改代码
SQL 代码
SQL 代码

这里是customersearch.egl 文件的完整代码(egl_code02-01-02b.html,文件的压缩包可以通过教程的 下载 部分获得)。如果您在文件中看到以红色 X 符号标记的出错地方,确保您的代码匹配 egl_code02-01-02b.html 文件中的代码。

既然现在您已经在 JSF handler 中建立了数据和函数,您就可以在页面中使用它们。

  1. 打开customersearch.jsp 页面。
  2. 在 Page Data 视图下,展开 JSF Handler
  3. 拖拉numberOfResults 变量,直接到 Submit 按钮下的输出文本区域的左边。
  4. 拖拉resultMessage 变量直接到右输出文本区域。
  5. 拖拉searchFunction()直接到页面的 Submit 按钮上。这时页面的外观并不改变,但是函数已经捆绑到按钮上。
  6. 保存页面。
  7. 通过在服务器中运行页面,并向其输入搜索项,来测试页面:
    1. 在 Project Explorer 视图中,右击 customersearch.jsp 然后点击 Run > Run on Server。在前面的教程中,您已经为项目建立了一个默认的服务器。如果您还没有完成这点(或者您已更改了设置),那么您不得不选择,再使用哪个服务器。
    2. 当在 Web 浏览器中打开页面后,在 LastName 区域输入一个词,在 State 区域输入一个状态,然后按下 Submit 按钮。记住搜索页面是 case sensitive 的。

例如,如果您在 LastName 区域输入F,在 State 区域输入NJ,那么页面将会显示如图 9 所示的结果。

图 9. 名字以 F 开头 NJ 的用户
带 e-mail 地址的名 Filibuster
带 e-mail 地址的名 Filibuster

该搜索页面使用起来很困难,因为用户必须同时知道用户的状态,以及用户名字的首字母。如果用户能在 AND 搜索与 OR 搜索之间选择,情况会更好一点 。在紧接着的下章节中,您将向页面添加该选项 。在更下面的章节中,您将把 State 输入区域改为一个组合框,该组合框列出了数据库中所有可用的状态。

分讲总结

您创建了 EGL 代码,该代码赋予前面您所创建的搜索页面以搜索功能。在本章节中,您学习了怎样完成以下目标:

  • 创建了一个包含函数的 EGL 列表库
  • 编辑并向 EGL JSF Handler 添加代码,以访问列表库中的函数
  • 捆绑 JSF Handler 中的函数到 Web 页面的控制按钮

下面您将开始学习第三讲:使用 OR 搜索条件

第三讲:使用 OR 搜索条件

在本讲中,您向允许用户在 AND 与 OR 搜索条件之间选择的页面,添加一个 radio 按钮组。当您运行该页面时,它看起来如图 10 所示。

图 10. 带 AND 与 OR 选择选项的搜索页面
AND 与 OR 标签旁的 radio 标签
AND 与 OR 标签旁的 radio 标签

在前面的章节中,您添加了一个以 AND 条件搜索的函数。在接下来的步骤中,您将添加一个以 OR 条件搜索的函数。通过这种方式,用户将能够搜索到,符合名字以及状态两者其一条件的记录。

  1. 打开 SearchLibrary.egl 列表库文件。
  2. 向文件添加如列表 12 所示的代码,刚好位于最终end 申明之前:
列表 12. 以 OR 条件查询的 SQL 语句
function NameAndStateSearch_Or(lname string in, 
  state char(2) in, 
  customer Customer[])
  get customer with
    #sql{
      select
                          EGL.CUSTOMER.CUSTOMER_ID, EGL.CUSTOMER.FIRST_NAME, 
                          EGL.CUSTOMER.LAST_NAME, EGL.CUSTOMER.PASSWORD, 
                          EGL.CUSTOMER.PHONE, EGL.CUSTOMER.EMAIL_ADDRESS, 
                          EGL.CUSTOMER.STREET, EGL.CUSTOMER.APARTMENT, 
                          EGL.CUSTOMER.CITY, EGL.CUSTOMER."STATE", 
                          EGL.CUSTOMER.POSTALCODE, EGL.CUSTOMER.DIRECTIONS
                  from EGL.CUSTOMER
      where EGL.CUSTOMER.LAST_NAME like :lname 
        or EGL.CUSTOMER."STATE" = :state
      order by
        EGL.CUSTOMER.CUSTOMER_ID asc
    };
end
  1. 该函数与您在前面章节中添加的NameAndStateSearch_And()函数相类似,不同之处在于,在 where 申明处,该函数使用OR,而不是AND
  2. 保存文件。
  3. 通过按下 Ctrl+G 键,或者右击文件后,点击 Generate,可为列表库文件生成Java™。
  4. 关闭文件。

这里是 SearchLibrary.egl 文件的完整代码(egl_code02-01-03a.html,文件的压缩包可以通过教程的 下载 部分获得)。如果您在文件中看到任何以红色 X 符号标记出来的出错地方,确保您的代码与 egl_code02-01-03a.html 文件的代码相一致 。

向页面添加一个 radio 按钮组

既然现在您已经有了两种不同的搜索函数,您需要向页面添加一个 radio 按钮,这样用户可以选择,使用哪种类型的搜索。

  1. 返回到 customersearch.jsp 文件。
  2. 通过将鼠标光标置于Submit按钮的左边,并按下 Enter 键,在 Submit 按钮之上添加一个新行。
  3. 在 Palette 中,打开 Enhanced Faces Components 折叠项。
  4. 拖拉 Radio Button Group 到新行中。
  5. 点击 radio 按钮组并选中它 。
  6. 如果您还没打开 Properties 视图,通过点击 Window > Show View > Properties 来打开它。
  7. 在 Properties 视图中,在 Add Choice 按钮的右边点击。这时 radio 按钮组的一个新选择,将列于表格中按钮的左边 。
  8. 在新选择的 Label 区域里,输入AND
  9. 在该选择的 Value 区域里,输入AND
  10. 再次点击 Add Choice
  11. 在二次选择的 Label Value 区域里,输入OR
  12. 当您完成后,properties 视图看起来如图 11 所示。
图 11. Properties 视图中的 Labels 与 Values
selectOneRadio 标签
selectOneRadio 标签
  1. 保存页面。

当您完成添加 radio 按钮组以后,搜索页面看起来如图 12 所示。

图 12. Radio 按钮组
搜索带 radio 选项的页面
搜索带 radio 选项的页面

接下来,您必须调试 JSF Handler ,以使用 radio 按钮的输入,来决定使用哪个搜索函数。

  1. 在页面上右击,并点击 Edit Page Code。在编辑器中打开 customersearch.egl 文件。
  2. 在 handler 的顶部,向变量申明添加如列表 13 所示的代码行:
列表13. 添加 andOr
andOr char(3);
  1. 接下来,您要向 radio 按钮捆绑该变量。它要么含有值AND,要么含有值OR,这取决于页面中选择了哪一个 radio 按钮。
  2. 用下面的新版本代替searchFunction()函数:
列表 14. 可以进行 AND 与 OR 功能两种搜索
function searchFunction()
  searchTerms.LastName = searchTerms.LastName+"%";
  
  if (andOr == "AND")
    SearchLibrary.NameAndStateSearch_And(
      searchTerms.LastName, 
      searchTerms.State, searchResults);
  else
    SearchLibrary.NameAndStateSearch_Or(
      searchTerms.LastName, 
      searchTerms.State, searchResults);
  end
  
  resultMessage = "Customer(s) found.  Search again?";
  numberOfResults = searchResults.getSize();
  
end
  1. 该函数与您在前面章节中添加的函数类似,不同点如下:
    • 特征变量andOr 代表了所选择的 radio 按钮的值,要么是AND,要么是OR
    • 现在搜索函数有一个if 申明。如果用户选择的是 AND radio 按钮,那么函数使用列表库中的NameAndStateSearch_And()函数。否则,它使用NameAndStateSearch_Or()函数。
  2. 保存,关闭并生成文件。
  3. 返回到 customersearch.jsp 页面。
  4. 在 Page Data 视图下,通过拖拉变量andOr - char(3)到页面 radio 按钮组上,将该变量与 radio 按钮组捆绑起来。
  5. 将函数searchFunction()与页面中的按钮 Submit 捆绑起来。
  6. 保存页面。
  7. 测试页面。试着使用新的 radio 按钮函数。要想让搜索页面正常的工作,您必须选择 radio 按钮组中的一个。

该搜索页面使用起来仍然很困难,因为在简单的数据库中并无多少记录,或者需要查找太多的状态。在接下来的章节中,您将要把 State 输入区域,改为一个组合框,该组合框列出了数据库中所有可用的状态。

这里是 customersearch.egl 文件的完整代码(egl_code02-01-03b.html,文件的压缩包可以通过教程的 下载 部分获得)。如果在文件中看到以红色 X 符号标记的出错地方,确认您的代码匹配 egl_code02-01-03b.html 文件中的代码 。

分讲总结

现在您有了同时基于两种参数进行搜索的搜索页面,或者找到匹配其中一个参数,而不匹配另外一个的结果。在本讲中,您学习了如何完成以下事项:

  • 在您的 EGL 列表库中,向搜索函数添加一次 OR 搜索
  • 向您的搜索页面添加一个 radio 按钮组
  • 向 JSF Handler 添加 OR 搜索页面
  • 向 radio 按钮组捆绑新搜索函数

现在您将开始学习第四讲:创建一个动态的组合框。

第四讲:创建一个动态的组合框

在本讲中,通过在一个组合框内,列出了用户状态的可能选择,改进了搜索页面。

为了让搜索尽可能的方便用户使用,通过简化任何时候用户作出决定的过程,您可以避免产生一些用户错误。在本讲中,通过用一个组合框取代 State 输入区域,您可以学到,怎样让用户使用搜索页面起来更简单 。该组合框只列出了,那些在数据库中至少代表一个用户记录的状态,以便不必让用户必须决定,使用哪个状态。

向列表库添加代码

首先,您需要向您的列表库添加一个函数,该列表库能获得数据库中的每一个状态。该函数比列表库中的其他函数都要简单,因为您只需从数据库中获得一列。另外,您可以使用一列用户记录,以当作状态信息,但是一列字符串处理起来更加容易,因为您不需要记录中剩余的区域。

  1. 打开 SearchLibrary.egl 文件。
  2. 向列表库添加如列表 15 所示的函数:
列表 15.获得状态
function getAllCustomerStates(listOfStates string[])
  customers Customer[0];
  counter int;
  
  get customers with
    #sql{
      select EGL.CUSTOMER."STATE"
      from EGL.CUSTOMER
      group by EGL.CUSTOMER."STATE"
      order by EGL.CUSTOMER."STATE" asc
    };

  listOfStates.removeAll();
  for (counter from 1 to customers.getSize() by 1)
    listOfStates.appendElement(customers[counter].State);
  end

end
  1. 保存文件。
  2. 生成列表库。

这里是您刚刚添加的getAllCustomerStates()函数的一些技术注意点:

  • 该函数以和getAllCustomers()函数同样的方式,访问数据库中的用户记录 。主要的不同点是,函数getAllCustomerStates()只选择 STATE 区域,而不是 Customer 表中的所有区域 。
  • SQL 命令组group by 通过状态组织结果,这样每种装态只在结果中列出一次。
  • SQL 命令组order by 将结果按字母顺序排列 (asc 关键词指示升序排列)。
  • for 只将状态区域从记录,移到一列字符串 。

这里有 SearchLibrary.egl 文件的完整代码(egl_code02-01-04a.html,文件的压缩包可以通过教程的 下载 部分获得)。如果您在文件中看到以红色 X 符号标记的出错地方,确保您的代码匹配 egl_code02-01-04a.html 文件中的代码。

向 JSF handler 添加代码

  1. 返回到 customersearch.jsp 页面。
  2. 在 customersearch.jsp 页面内右击并点击 Edit Page Code
  3. 在行andOr char(3);之后,添加如列表 16 所示的代码行。
列表 16. 添加 customerStates 字符串
customerStates string[0];
  1. 该变量记录了列表库中函数的返回状态。
  2. Function onPreRender()之后添加一个空白行,然后在空白行中,添加如图 17 所示的代码行。
列表 17. 获得状态
SearchLibrary.getAllCustomerStates(customerStates);
  1. 保存文件。
  2. 生成文件。

在您完成后,文件 customersearch.egl 看起来如图 13 所示(有一些函数被压缩了,由页面左边距内的加号标示):

图 13. 修改后的代码
EGL 代码
EGL 代码

对于您刚添加的代码,有一些技术注意点:

  • 数组customerStates 记录了数据库中,至少有一个用户代表的状态。
  • 您向函数onPreRender 添加的行,发送数组 customerStates 至列表库中的函数getAllCustomerStates,用状态列创建数组。

这里是文件 customersearch.egl 的完整代码(egl_code02-01-04b.html,文件的压缩包可以通过教程的 下载 部分获得)。如果在文件中看到以红色 X 符号标记的出错地方,确认您的代码匹配 egl_code02-01-04b.html 文件中的代码 。

向页面添加组合框

添加一个动态的组合框,比添加一个预定义值的 JSF 控制器,例如您在前面章节中添加的 radio 按钮组,要更加复杂一些。该组合框必须联系两种 EGL 数据:

  • 数组 customerStates,它提供组合框的选项列。
  • 变量searchTerms.State,它记录了用户对组合框的选择。

完成以下步骤:

  1. 返回至 customersearch.jsp 页面。
  2. 点击 STATE 输入区域以选中它,并按 Delete 键。输入区域从页面中移除。
  3. 在 Palette 中,打开 Enhanced Faces Components 折叠项。
  4. 拖拉 Combo Box 项到页面上,并将其放到 STATE 输入区所在的地方。
  5. 在 Page Data 视图中,展开 searchTerms - Customer
  6. 在 Page Data 视图的 searchTerms - Customer 之下,拖拉 State - State 至组合框。
  7. 点击组合框以选中它。
  8. 打开 Properties 视图。在 Properties 视图中,注意区域 Value 被设置成#{customersearch.searchTerms.State},意味着组合框中的选择值,被置于searchTerms 记录的State 区域内。
  9. 在 Properties 视图下 ,点击 Add Set of Choices,它位于视图的最右边,靠近选择表的地方。带有标签<selectitems>以及一个默认值的新项目被添加到选择列。标签<selectitems>是一个代表多重选项的 JSF 标签,而不是一个单值静态标签。换句话说,组合框使用了您在 Value 列中指定的值, 即组合框中的标签以及该标签代表的值。
  10. 在标签<selectitems>旁边,点击 Value 区域附近的 Select Page Data Object 按钮。打开 Select Page Data Object 窗口。
  11. 在 Select Page Data Object 窗口中,点击 customerStates - string[]

Select Page Data Object 窗口看起来如图 14 所示:

图 14. 选择页面数据对象
在树形视图中选中的 State - State
在树形视图中选中的 State - State

ALT:

  1. 点击OK。现在组合框的选择来自变量customerStates,同时组合框的选择状态放在变量 searchTerms 中。
  2. 保存页面。
  3. 测试页面。

分讲总结

在创建一系列搜索参数的 Web 页面中,您已经创建了一个组合框。

在本讲中,您已经学习了完成以下事项:

  • 向列表库添加代码,完成一次有限搜索
  • 向 JSF Handler 添加代码,以访问修改后的搜索参数
  • 向 Web 页面添加一个组合框
  • 将修改后的搜索函数与组合框联系起来。

现在您将开始学习第五讲:编辑搜索结果。

第五讲:编辑搜索结果

在本讲中,您将学着制作一个更加复杂的数据表,以显示出您的搜索结果。

到目前为止,每一个您向 Web 页面添加的 JSF 组件,都与单值数据库表格的一个数据相对应 。如果要使用一个更加复杂的关系数据库,那么每次您要处理来自多个表格的数据 。

在本讲中,通过显示来自 Customer 表与 State 表中的数据,您可以定制搜索结果。通过这种方式,结果将同时显示用户名(来自 Customer 表)与用户状态的全名(来自 State 表),而不再是两个词的缩写。通过组合用户的姓与名成为一个完整的名字,您也可以掌控搜索结果。结果得到的数据表看起来如下图所示:

图 15. 从两个数据表中组合信息
全名, e-mail 地址,以及状态全名
全名, e-mail 地址,以及状态全名

创建一个这样的自定义数据表的最简单方式,是创建一个在该数据表中代表单个记录的自定义 EGL 记录。然后,您建立一系列与数据表相联系的记录。在本讲中,您创建的自定义 EGL 记录有以下三个区域 :

  • email 区域,它记录了来自 Customer 表中用户的 e-mail 地址。
  • fullName 区域,它记录了来自 Customer 表用户的姓与名的组合 。
  • State 区域,它记录了用户状态的全名。为了得到全名,搜索功能交叉参考了Customer 表,与 State 表中的一系列简写和状态名中的用户状态缩写。

向列表库添加代码。

完成以下步骤。

  1. 打开 SearchLibrary.egl 文件。
  2. 向列表库添加如列表 18 所示的函数。
列表 18. 从 State 表中获得数据
function getOneState(state Statetable)
  get state;
end
  1. 文件 Statetable.egl 定义了 stateTable 记录,所以如果您还没有使用完成代码,来输入该函数,那么您就必须引入该记录。
  2. 在刚刚位于行 package libraries;之后的地方,向文件 SearchLibrary.egl 添加如下的申明,如列表 19 所示。
列表 19. 引入记录
import eglderbyr7.data.Statetable;
  1. 在刚刚位于列表库中最终end 申明之后的地方,向文件添加如列表 20 所示的代码。
列表 20. 为字符串定义 displayNames
Record customizedResult type basicRecord
  fullName   string
    {displayName = "Full Name"};
  email      string
    {displayName = "Email Address"};
  stateName  string
    {displayName = "State"};
end

注意:因为列表库本身不包含 Record 定义,所以在关闭列表库的end 申明之后,您必须添加customizedResult 记录定义。

  1. 保存文件。
  2. 生成文件。

这里有 SearchLibrary.egl 文件的完整代码(egl_code02-01-05a.dita,文件的压缩包可以通过教程的 下载 部分获得) 。如果在文件中看到以红色 X 符号标记的出错地方,确认您的代码匹配 egl_code02-01-05a.dita 文件中的代码 。

向页面代码文件添加代码

  1. 返回至 customersearch.jsp 页面。
  2. 在 customersearch.jsp 页面内右击并点击 Edit Page Code
  3. customerStates string[0];行之后,向 JSF Handler 添加如下变量定义,如列表 21 所示。
列表 21. 定义 allRecords 变量
allRecords customizedResult[0];
  1. 该变量代表了新的搜索结果,该结果基于您刚刚创建的自定义记录。
  2. 如果您不使用完整代码,以插入这个代码行,那么您可以在 package jsfhandlers;行之下,向 JSF Handler 添加如列表 22 所示的import 声明。
列表 22. 引入申明
import libraries.customizedResult;
  1. 向 JSF handler 添加如列表 23 所示的函数。
列表 23. 生成结果函数
function generateCustomResults(passedResults Customer[])
  allRecords.removeAll();
  oneRecord customizedResult;
  counter int = 1;
  state Statetable;
    
  //loop once for each search result returned
  while (counter <= (passedResults.getSize()))
              oneRecord.fullName = passedResults[counter].FirstName ::
                " " :: passedResults[counter].LastName;
              oneRecord.email = passedResults[counter].EmailAddress;
              state.StateAbbrev = passedResults[counter].state;
              SearchLibrary.getOneState(state);
              oneRecord.stateName = state.StateName;
              allRecords.appendElement(oneRecord);
              counter = counter + 1;
  end
end
  1. 该函数集中了自定义的搜索结果。您必须在searchFunction() 函数的末尾访问该函数。
  2. 在 JSF Handler 中关闭searchFunction()函数的end 申明之前,添加如列表 24 所示的代码行。
列表 24. 生成结果
generateCustomResults (searchResults);
  1. 保存文件。

通过完成以下这些通用步骤,您向 JSF handler 添加的新函数集中了自定义的搜索结果:

  1. 从姓与名集合得到用户的全名。
  2. 得到用户的 email 地址。
  3. 得到用户状态的缩写。
  4. 查找匹配缩写的状态名。
  5. 向数组allRecords添加全名,email 地址,状态名。

这里有 customersearch.egl 文件的完整代码(egl_code02-01-05b,文件的压缩包可以通过教程的 下载 部分获得)。如果在文件中看到以红色 X 符号标记的出错地方,确认您的代码匹配 egl_code02-01-05b.html 文件中的代码 。

创建自定义数据表

  1. 返回至 customersearch.jsp 页面。
  2. 如果想要去掉旧的搜索结果,您可以删掉旧的数据表。为了完成这点可以作以下步骤:
    1. 在旧的搜索结果表中的任何地方点击,以把鼠标光标定到那里。
    2. 按下向下的箭头键。此时整个数据表被选中。
    3. 按下 Delete 键。此时数据表从页面中被删除掉。
  3. 在 Page Data 视图中,拖拉 allRecords - customizedResult[]到页面上,刚好位于旧的数据表所在的位置之下。打开 Insert List Control 窗口。
  4. 点击 Displaying an existing record (read-only)旁边的 radio 按钮。
  5. 点击 Finish。新的数据表已在页面中创建出来。
  6. 保存页面。
  7. 测试页面。

现在当您搜索用户时,您可以在数据表中看到用户的全名,e-mail 地址,以及状态全名。页面的外观如图 16 所示 。

图 16. 整个结果显示后的搜索
结果显示出全名,e-mail 以及全状态
结果显示出全名,e-mail 以及全状态

分讲总结

通过把姓与名组合成一个完整的名字,以及把状态区域的双字节代码装换成为状态的全名,您可以自定义您的搜索结果。

在本讲中,您要学习怎样完成以下事项:

  • 向自定义结果的列表库添加一个函数
  • 在列表库自身以外的地方,向列表库文件添加一项记录
  • 向 JSF Handler 添加新的自定义结果函数
  • 在 Web 页面上放置一个新的结果表
  • 将新结果函数与表格联系起来

第 6 讲:使用 type-ahead 技术以方便用户使用

使用 type-ahead 技术,试着预测用户将向输入区域输入的内容,加快输入信息的过程 。在本讲中,您将学着创建一个独立的搜索页面,与前面的页面相比,该页面使用 type-ahead 功能进行搜索。

Type-ahead 功能使用 Ajax (Asynchronous Java™Script and XML),后者是一种在不重新加载整个页面的前提下,允许 Web 应用程序改变部分 Web 页面的网络技术。在这种情况下, Ajax 功能允许让您的 EGL JSF Handler ,在不重新提交页面的基础上,向输入控件添加或者移除建议。

EGL type-ahead 功能向 Ajax 功能的普遍应用,提供了一种快捷方式,这就意味着您不必自己组合一项 Ajax 请求。在接下来的章节中,您将要创建这样的通用 Ajax 请求。

按照惯例,带 type-ahead 的输入控件提供的选项,是基于用户向输入区域输入的前几个字母的,如图 17 所示。

列表 17. Type-ahead 建议选项
用户种类 's'

但是,取决于您怎样为 type-ahead 书写 EGL 代码,您要么可以提供基于输入前几个字母的建议,要么可以提供一个动态提供建议的任意函数 。

为了让 type-ahead 提供基于输入前几个字母的建议,您必须在特定的时间内指定那些建议,要么在validValues 属性内,要么在 Data Table 部分中。本范例使用的是validValues 方法,如列表 25 所示。

列表 25. 基于有用建议的 Type-ahead 技术
state STRING {typeahead = YES, 
   validValues = ["AK","AL","AR","AZ",
      "NC","NY","NH","NJ",
      "NM","NE","NV","ND"]};

在该变量中,有用值是以“A”和“N”开头的 U.S. 状态的缩写。当用户向输入控件输入字母“A”时,type-ahead 将提供以“A”开头的缩写,同样的,如果输入字母“N”,那么就提供以“N”开头的缩写。

在本讲中,您使用了 type-ahead 功能,以提供数据库中用户名的建议,方便用户的搜索。在这种情况下,您必须在运行时决定 type-ahead 提供的建议,因为建议是基于数据库中值的 。因此,您要在新的 JSF Handler中创建一个函数,该函数能够将用户在输入区域输入的内容,与数据库中用户名进行比较。然后该函数将提供与之匹配的名字,以作为 type-ahead 建议。

  1. 在名为customersearchAjax.jsp 的 EGLWeb 项目中创建一个新的 Web 页面:
    1. 在 Project Explorer 视图中,点击 EGLWeb 项目的 WebContent 文件夹以选中它。
    2. 点击 File > New > Other
    3. 在 New 窗口中,展开 Web 并点击 Web page
    4. 点击 Next
    5. File Name 区域中,输入customersearchAjax.jsp 以作为新文件,包括扩展的名字。
    6. 检查并确保 Folder 文件夹显示的是 /EGLWeb/WebContent 文件夹。
    7. Template 列表中,点击 My Templates
    8. Preview 框中,点击 A_gray.htpl 模板。
    9. 点击 Finish。新的页面在编辑器中被创建并打开。
    10. 从页面中移除默认文本。
  2. 通过在页面的内容区域右击,然后选择 Edit Page Code,打开页面的 JSF Handler。
  3. 向 JSF Handler 添加如列表 26 所示的三个变量(lastNameInput,allLastNames,以及 customerToDisplay):
列表 26. 添加变量
lastNameInput string {TypeaheadFunction = suggestLastNames};
allLastNames Customer[0];
customerToDisplay Customer;
  1. 第一个变量与页面的输入控件联系起来。属性 TypeaheadFunction 指示该变量将有一个提供 type-ahead 建议的函数。您将在本讲的稍后内容中创建该函数 。
  2. 第二个变量记录了数据库中一系列的名字。函数提供的建议需要这个列表。
  3. 第三个变量是一个显示搜索结果的单个记录。
  4. 如果您不使用帮助添加这些变量的内容,向页面添加如列表 27 所示的import 申明:
列表 27. 引入申明
import eglderbyr7.data.Customer;
  1. 在 JSF Handler 中除掉onConstructionFunction 属性,并将其替换成onPreRenderFunction,如列表 28 所示。
列表 28. 替换属性
handler customersearchAjax type JSFHandler
  {onPreRenderFunction = onPreRender,
  view = "customersearchAjax.jsp"}
  1. 向 JSF Handler 添加如列表 29 所示的函数 。
列表 29. 添加 onPreRender() 函数
function onPreRender()
  get allLastNames with
    #sql{
      select
        EGL.CUSTOMER.LAST_NAME
      from EGL.CUSTOMER
      group by
        EGL.CUSTOMER.LAST_NAME
    };
end
  1. 每当页面刷新时,该函数就会运行,以便和用户的输入相比较,进而从数据库中获得一系列的用户名。
  2. 向 JSF Handler 添加如列表 30 所示的函数。
列表 30. 添加 suggestLastNames 函数
function suggestLastNames(typedCharacters string in) returns (string[])
    matchingLastNames string[0];
    oneCustomer Customer;
    oneCustomerName string;
    
    //This variable represents the characters the user has typed.
    typedCharacters = StrLib.upperCase(typedCharacters);
    
    //Compare the user input to the values in the database.
    for (counter int from 1 to allLastNames.getSize())
      
      oneCustomer = allLastNames[counter];
      oneCustomerName = StrLib.upperCase(oneCustomer.LastName);
      
      if (StrLib.indexOf(oneCustomerName, typedCharacters) == 1)
        //This value starts with the same characters.
        //Add this value to the type-ahead suggestions.
        matchingLastNames.appendElement(oneCustomer.LastName);
      end
      
    end
    
    return (matchingLastNames);
    
end
  1. 该函数就是您在前面创建的变量的TypeaheadFunction 属性引用过的函数。正如其名字暗示的那样,该函数为 type-ahead 提供建议。该函数必须接受单个参数:一个代表用户向输入控件输入内容的 STRING,以此作为建议。有了这个函数,您就可以通过任意的 EGL 逻辑,决定采用哪个 type-ahead 建议。
  2. 在这种情况下,函数遵循惯例:建议应该始于,与用户向输入控件输入内容相同的词语。函数将用户输入的内容,与每个用户的名相比较,并将每个名字都改为大写,以消除大小写所带来的差异。每当函数找到一个相匹配的名字,就会向作为 type-ahead 建议的结果数组,添加用户名。
  3. 向 JSF Handler 添加如列表 31 所示的函数。
列表 31. 添加 displayCustomer() 函数
function displayCustomer()
    get customerToDisplay with
      #sql{
        select
          EGL.CUSTOMER.CUSTOMER_ID, EGL.CUSTOMER.FIRST_NAME, 
          EGL.CUSTOMER.LAST_NAME, EGL.CUSTOMER.PASSWORD, 
          EGL.CUSTOMER.PHONE, EGL.CUSTOMER.EMAIL_ADDRESS, 
          EGL.CUSTOMER.STREET, EGL.CUSTOMER.APARTMENT, 
          EGL.CUSTOMER.CITY, EGL.CUSTOMER."STATE", 
          EGL.CUSTOMER.POSTALCODE, EGL.CUSTOMER.DIRECTIONS
        from EGL.CUSTOMER
        where
          EGL.CUSTOMER.LAST_NAME = :lastNameInput
      };
end
  1. 该函数将会与页面中的按钮联系起来。当 type-ahead 控件帮助用户找到一个特定用户的名字时,用户可以点击按钮,并运行函数以获得用户的具体信息。
  2. 保存 JSF Handler 文件。
  3. 在 customersearchAjax.jsp 页面中,拖拉 Page Data 视图中的lastNameInput 变量到页面中,打开 Insert Record 窗口。
  4. 点击 Updating an existing record 并确保输入控件的 Control type 值被设置成为 Input Field。您可以只在 JSF 输入控件中使用 type-ahead 技术。
  5. 点击 Options
  6. 在 Options 窗口中,清除 Delete 按钮复选框的选择,并选中 Submit 按钮复选框的选择。
  7. 点击 OK
  8. 点击 Finish。页面中创建了输入控件与一个按钮。因为变量的 TypeaheadFunction 属性,新的输入控件自动设置成为 type-ahead。通过点击输入控件右边的 type-ahead 图标,并打开 Properties 视图,您可以查看选项的 type-ahead 功能,例如在提供建议前的延迟时间,如图 18 所示。
图 18. Type-ahead 选项
属性标签
属性标签
  1. 拖拉 Page Data 视图中的CustomerToDisplay 变量到页面的底部。打开 Insert Control 窗口。
  2. 在 Insert Control 窗口中,点击 Displaying an existing record (read-only)
  3. Fields to display 之下,选中您想要在搜索结果中,显示的用户记录区域旁的复选框。例如,您可以选中 CustomerIdFirstNameLastName 以及 Phone 区域,如图 19 所示。
图19. 选择要显示的区域
设置信息控件
设置信息控件
  1. 点击 Finish。在页面中添加了代表搜索结果的控件 。
  2. 通过拖拉 Page Data 视图中的函数 displayCustomer()到按钮 Submit 之上,将函数与按钮联系起来。
  3. 现在您可以把页面设置成使用 type-ahead。页面的外观如图 20 所示 。
图 20. 设置搜索页面
输入在页面顶部,具体信息在底部
输入在页面顶部,具体信息在底部
  1. 通过在服务器中运行页面,并向输入区域输入用户名的一个或两个字母,来测试页面,如图 21 所示。
图 21. Type-ahead 提议
用户种类 's'
用户种类 's'
  1. 当您选中一个用户的名字后,您可以点击 Submit,然后查看用户的信息,如图 22 所示。
图 22. 选择显示的用户信息
用户名的具体信息

这里有 customersearchAjax.egl 文件的完整代码(egl_code02-01-06.html,文件的压缩包可以通过教程的 下载 部分获得)。如果在文件中看到以红色 X 符号标记的出错地方,确认您的代码匹配 egl_code02-01-06.html 文件中的代码 。

分讲总结

在本讲中,您学习了应用 type-ahead 技术以支持一个输入区域。Type-ahead 可以帮助用户输入有用信息,但是同时您要意识到,系统提供建议所面临的压力。每次输入控件的值改变时,与 type-ahead 控件相联系的函数就会运行。该函数应该尽可能的简单,以避免让系统超负荷运作。

第 7 讲:创建一次通用 Ajax 请求

在本讲中,您要学习创建一次 Ajax 请求,以加快 JSF Handler 与 Web 页面之间的交流速度。

在前面的章节中,您向输入控件添加了 type-ahead 技术支持。通过自动生成的 Ajax 请求,改变输入控件的值,访问在联系变量的 TypeaheadFunction 属性指定的函数。函数改变了页面的一小部分,并在不打断页面中用户进程的前提下,向输入区域添加 type-ahead 建议。进程对用户不可见,并且(如果运行的更加有效)与用正常的方式,在 JSF Handler 中提交页面与访问函数相比,要更加快捷。

同样的,当输入控件的值发生改变时,您可以添加活动的通用 Ajax 请求。当页面向 JSF Handler 传递该 Ajax 请求时,在 onPreRenderFunction 属性中指定的函数会运行,当用户仍然在浏览页面时,允许您去运行逻辑。当 Ajax 请求访问函数时,函数可以改变 JSF Handler 中变量的值,但是这些改变不会在页面的控件中自动反映出来。相反的, Ajax 请求指定了一块改变页面的区域,只有这块区域中的页面改变,才会反映出 JSF Handler 作出的改变。

对于本文的应用,您可以添加 Ajax 功能,以让搜索函数运行的更快。在前面的分讲中,您必须按下按钮以搜索某个记录,并重新加载进程中的整个页面。而在本讲中,在不重新加载整个页面的前提下,您就可以更改页面的部分结果。为了做到这点,您需要完成以下步骤:

  1. 指示出由于 Ajax 请求而做出改变的页面段落。
  2. 将一项 Ajax 请求与页面的段落联系起来。在请求中,您将传递一个参数,该参数记录了输入到页面输入控件的当前值 。
  3. 在 JSF Handler 中向 onPreRender 函数添加代码,以回应请求。在这种情况下,函数将执行搜索,并更改带搜索结果页面的指示段落。
  4. 向输入控件添加一个指示器,以激活 Ajax 请求。

完成以下步骤:

  1. 打开 customersearchAjax.egl 文件。
  2. 用如列表 32 所示的函数,替换已存在的 onPreRender 函数。
列表 32. 修改 onPreRender 函数
function onPreRender()
  submittedLastName string;

  if (J2EELib.getQueryParameter("$$ajaxmode") == NULL)
    //Refresh is not the result of an Ajax request.
    //Retrieve the customer names for the type-ahead function.
    get allLastNames with
      #sql{
        select
          EGL.CUSTOMER.LAST_NAME
        from EGL.CUSTOMER
        group by
          EGL.CUSTOMER.LAST_NAME
      };
  else
    //Refresh is the result of an Ajax request
    //Check to see if the last name typed in exists in the list of customers
    submittedLastName = J2EELib.getQueryParameter("textLastNameInput1");
    
    for (counter int from 1 to allLastNames.getSize())
      if (StrLib.upperCase(submittedLastName) == 
        StrLib.upperCase(allLastNames[counter].LastName))
        //The value in the input control matches a record.
        //Display the customer record.
        lastNameInput = submittedLastName;
        displayCustomer();
        exit for;
      end
    end
        
  end
    
end
  1. 该函数分支基于值 J2EELib.getQueryParameter("$$ajaxmode")。该系统函数返回随 Ajax 请求传递的参数的值。为了探测函数 onPreRender 是由于正常页面载入而运行,还是由于 Ajax 请求而运行,您可以检查应用参数 $$ajaxmode 的值,如果函数 J2EELib.getQueryParameter("$$ajaxmode") 返回一个空值,那么页面载入正常,如果它返回其他的任何值,那么函数 onPreRender 是由一次 Ajax 请求访问的。
  2. 如果页面载入正常,那么函数 onPreRender 将从数据库中获得用户名,就像它在前面章节中做得那样。但是,如果 JSF Handler 获得一次 Ajax 请求,那么函数将文本值与数据库中的一系列名字相比较。如果用户向输入控件输入的内容,与数据库中的一个名字相匹配,那么像上面章节一样,使用函数 displayCustomer,JSF Handler 将会显示出该数据库记录。
  3. 这就是 JSF Handler 使用 Ajax 唯一需要作出的改变。但是,您必须设置 JSP 成,向 JSF Handler 发送 Ajax 请求,并获得改变情况。为了做到这点,从页面中移除已存在的控件,再重新启动,会更加容易一点。
  4. 在 customersearchAjax.jsp 页面上,从页面中移除所有已存在的控件与文本。通过按下 Ctrl+A 键再按 Delete 键,您可以迅速完成这步。
  5. 就像您在前面所做的一样,为变量 lastNameInput 创建输入控件。
    1. 在 Page Data 视图中,拖拉变量lastNameInput 到页面中。打开 Insert Record 窗口。
    2. 点击 Updating an existing record
    3. 点击 Options
    4. 清除 Delete button 复选框与 Submit button 复选框的选择。您不需要该页面中的任何按钮,因为 Ajax 请求执行该操作。
    5. 点击 OK
    6. 点击 Finish
  6. 确保输入控件的 ID 是 textLastNameInput1
    1. 点击输入控件以选中它。
    2. 在 Properties 视图中,确保 ID 区域被设置成为 textLastNameInput1。
  7. 到目前为止,页面已经与前面分讲中提到的页面类似。接下来,您将向页面添加 customerToDisplay 记录,以显示出搜索的结果 。
    1. 不是直接将其置于页面之上,您必须将其放到两个相联系 Group 框控件之上。
    2. 组合框控件自身并不可见;它们用作其他控件的容器。在这种情况下,您需要两种组合框:
      • 一个 group 种类的组合框,将会标记出 Ajax 请求更改后的页面部分 。通过只刷新页面的需要部分,而不是刷新整个页面,Ajax 被设计成一种更加高效的方式,因为您想要在不刷新页面的基础上,更改搜索结果,所以搜索结果必须位于组合框之中。
      • JSP 种类的组合框,允许您在其他组合框中,放置复杂的控件。而 group 种类的组合框,只包含有简单的控件,例如输入以及输出控件。您必须将创建的表格,由 customerToDisplay 记录转化成为一个 JSP 组合框。
  8. 在 Palette 视图下,展开 Enhanced Faces Components,并拖动 Panel - Group Box 到页面中,位于输入控件以下的地方。Select Type 窗口能方便您去选择一系列的组框。
  9. 在 Select Type 窗口中,点击 Group
  10. 点击 OK。新的组框出现在页面中,帮助您向页面添加内容。
  11. 通过点击组合框并选中它,然后在 Properties 视图中设定 ID updateBox ,来设置组框的 ID 为updateBox
  12. 向组框添加 Ajax 请求:
    1. 在选中组框后,打开 Properties 视图。
    2. 在 Properties 视图中,h:panelGroup之下,来到 Ajax 标签。
    3. 选中 Allow Ajax updates 复选框。
    4. Type of the Ajax request 之下,点击 Refresh。不同种类的 Ajax 请求决定了参数以何种方式传递给 JSF Handler。对于本页面,您将使用 Refresh 种类的 Ajax 请求,因为它是最简单的。
    5. 点击标有 Click to edit Ajax request properties 的按钮。Properties 视图显示出了 Ajax 请求的 ID 与参数。
    6. Parameter values sent from the browser 之下,点击 Add Parameter。就可以在 Parameter values sent from the browser 之下的列表中添加一个参数。
    7. Name 之下的拉下菜单中,选择 textLastNameInput1。现在输入控件的当前值,将会随着 Ajax 要求一道被传递。
      • 这种 Ajax 要求默认条件下不会传递任何参数,所以您必须定义出 JSF Handler 需要的参数。就算用户在页面的输入控件中输入了信息,当产生 Ajax 请求时,与输入控件相联系的变量的值还是不会被改变。
      • 因此,您必须在请求中,把控件的值当作一个参数传递。您在上面步骤中添加的onPreRender 函数得到带J2EELib.getQueryParameter()函数的参数,并直接将该值赋给变量。
  13. 您已经定义了将会传递给 JSF Handler 的 Ajax 请求,允许 JSF Handler 更改组合框中的内容。随后,您将向页面添加一个指示器,指示什么时候产生了 Ajax 请求。页面以及Ajax 请求如图 23 所示。
图 23. Ajax 请求
设计视图在顶部,Properties 标签在底部
设计视图在顶部,Properties 标签在底部
  1. 拖拉另一个 Panel - Group Box 到页面中,直接到第一个组合框中。该组合框必须位于第一个组合框之内。如果您不能将第二个组合框拖拉到第一个里面,一个最终的解决方法是在 Palette 视图中点击Panel - Group Box按钮,然后点击您将要放入新组合框的组合框。
  2. 在 Select Type 窗口中,点击 JSP
  3. 点击 OK
  4. 在 Page Data 视图中,拖拉 customerToDisplay 记录到 JSP 组合框中。打开 Insert Control 窗口。
  5. 在 Insert Control 窗口中,点击 Displaying an existing record (read-only)
  6. Fields to display 下面,从记录中选择一些区域,以显示在页面中。例如,您可以选择 CustomerIdFirstNameLastName以及 Phone 文件夹。
图 24. 选择显示的区域
设置信息控件
设置信息控件
  1. 点击 Finish
  2. 因为现在组合框中已经有内容,所以组合框自身在页面中并不可见。为了检查一个组合框的属性,选择组合框中的任意控件,然后在 Properties 视图下使用标签进入组合框 。在图 25 中,标签 h:panelGroup 代表 group 种类的组合框, 标签 fx:jspPanel 代表 JSP 组合框。
图 25. 组合框属性
outputText 标签
outputText 标签
  1. Ajax 请求现在已经就绪,而且由于请求而被改变的内容也已就绪 。最后一步是创建一个请求指示器。您可以在输入控件上创建该指示器,这样每当输入控件有所改变时, Ajax 请求都将传递给 JSF Handler。
  2. 点击输入控件以选中它。
  3. 在选中输入控件后,打开 Quick Edit 视图。
  4. 在 Quick Edit 视图中,点击 onChange 操作。这就意味着,当输入控件的值发生改变时,您在 Quick Edit 视图中定义的操作将会被执行。
  5. 选择 Use pre-defined behavior
  6. Action 列中,选择 Invoke Ajax behavior on the specified tag
  7. Target 列中,选择 updateBox。Properties 视图看起来应该如图 26 所示。
图26. 设置输入控件
Quick Edit 标签
Quick Edit 标签
  1. 保存页面。
  2. 测试服务器中的页面。
  3. 在经过这番调试后,如果用户允许 type-ahead 功能来填充数据库中的用户全名,然后将注意力从输入控件上转移走,那么 JSF Handler 将更改显示搜索结果的记录,如图 27 所示。
图 27. 自动显示的 Customer 具体信息(不需要 Submit )
名字的 Filibuster
名字的 Filibuster

这里有 customersearchAjax.egl 文件的完整代码(egl_code02-01-07.html,文件的压缩包可以通过教程的 下载 部分获得)。如果您在文件中看到以红色 X 符号标记的出错地方,确保您的代码匹配 egl_code02-01-07.html 文件中的代码。

分讲总结

在本讲中,您创建了一个通用 Ajax 请求,以更新页面的特定部分 。

当您想要改变一个很大页面的一小部分时,或者当您可以减少保存系统资源的请求时,Ajax 就变得十分有用。但是,潜在的代码可以变得十分复杂,所以一定要小心地组织并测试使用 Ajax 的页面。

在本讲中,您学到了以下内容:

  • EGL JSF Handlers 怎样处理 Ajax 请求
  • 怎样创建一个简单的 Ajax 请求,并传递该请求的一个参数
  • 怎样在页面内从用户操作中引发请求

总结

全文总结

这就是教程“使用 Rational Business Developer 基于 EGL 构建 JSF 搜索页面”的结尾。

学到的知识

在完成本篇教程的学习后,您可以学到怎样完成以下事项:

  • 创建一个简单的搜索页面
  • 创建一个包含了搜索页面要访问的函数的 EGL 列表库
  • 创建一个自定义 EGL 记录部分,并在页面中显示出来
  • 使用 EGL 代码中的 SQL 申明,以过滤搜索页面得到的结果
  • 在 Web 页面上创建 Enhanced JSF 组件,并将其与函数、变量联系起来
  • 修改您的搜索函数,以向用户提供搜索种类的选择
  • 自定义您的搜索结果
  • 对输入控件使用 type-ahead 技术支持
  • 创建一个简单的 Ajax 请求

在学完本篇教程后,您可能还想继续学习。您可以对您自己的页面添加如下功能:

  • 添加从搜索页面到 updatecustomer.jsp 页面的链接,后一个页面是您在前面部分中创建的。您需要让这个链接传递一个参数,就像您对 allcustomers.jsp 页面所做的一样。
  • 试着修改搜索结果,使其包含除用户姓名,e-mail 地址,所在州之外的其他信息。
  • 试着对项目的其他页面应用 type-ahead 技术支持或者 Ajax 请求。

下载资源


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Rational
ArticleID=336997
ArticleTitle=使用 Rational Business Developer 基于 EGL 构建 JSF 搜索页面
publish-date=09102008