Board logo

标题: 用动态元素自动更新 Web 页面 -2 更新数据模型和创建动态 GUI 元素 [打印本页]

作者: look_w    时间: 2018-8-23 21:00     标题: 用动态元素自动更新 Web 页面 -2 更新数据模型和创建动态 GUI 元素

更新数据模型和创建动态 GUI 元素构建了能监视服务器端数据变更的框架之后,如果需要这个 bean 在发生任何变更时都能被通知到,那么就要找到一种方法来更新数据模型和创建动态 GUI 元素。这个过程会在这个受管 bean 的内部发生(参见图 2 的 Bean 层),并且能够被分成两个子过程:更新数据模型和创建 GUI            元素。
更新数据模型这个子过程由之前在清单 3 中所示的 refresh() 方法调用。清单            4 展示了更新数据模型的方法。使用 refresh() 方法来重新组织库存以确保书籍被分配到正确的类别。因此,在更新了数据模型之后,就可以确保其下没有书的那些类别已被删除并且所有新的类别已被添加。
为了让您能更好地理解 refresh() 方法,我先来简单介绍一下我所使用的自定义的数据结构。我使用 Category            类来保存库存信息。Category 类包含类别名以及以 ArrayList<BookItem>.BookItem 类形式表示的书籍的元数据,这些元数据包括书名、作者、价格和类别。清单 4 展示了该如何更新数据模型。
清单 4. 更新数据模型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class InventoryBean implements InventoryListner{
...
       private Inventory m_notifier;
       private Category[] m_category;
       public InventoryBean(){
          m_notifier = Inventory.getInstance();
       }
       private void refresh(){
            //reorganize the data model
          ArrayList<Category> categoryList = m_notifier.reorgnizeCategory();
            // code for converting data to the type used in this bean,
           // ArrayList<Category> to Category[]   
       }
...
}




创建动态的 GUI 元素接下来,我将介绍另外的一个子程序:创建动态 GUI 元素。本例中的动态 GUI 元素是一些类别链接(参见图 1)。如果用户单击主页中的一个特定类别,他就会被重定向到一个包含此类别内所有书籍的新的页面。图 3 展示了属于侦探类别的所有书籍。
图 3. 侦探类别的细节要让这些类别链接发挥作用,需要删除旧的链接、将新的链接插入到网页中的合适位置,并将不同的类别细节信息绑定到不同的类别链接。
插入和删除链接有两种方式可以删除或插入链接。一种方法是查找 JSF 组件树中的动态元素的父组件,然后删除或插入元素。如果这些动态元素的父组件正在发生改变,就应该采用这种方法。另一种方法是直接将动态元素绑定到 Web 页面。这种方法比第一种方法简单,因为无需寻找 JSF 组件树中的父节点。不过,由于太过简便,这种方法具有一些限制:它只能用在所要删除或插入的元素具有固定的父组件并且在运行时之前父组件就已知的情况下。我之所以选用了这种方法(参见清单 5)是因为在本例中这些类别链接的父组件是固定的,并且也是预先定义了的。
清单 5. 创建/更新 GUI 组件并将不同的组件绑定到不同的动作处理程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
category.jsp
……
<f:view>
    <h:form id="helloForm">
     ……
      <h:panelGrid id="title">      
     <hutputText id = "hello_title" value="Inventory"/>
        <a4jutputPanel  id = "book"
                           binding = "#{InventoryBean.categorygrid}"/>
     ……
      </h:panelGrid>
    </h:form>
</f:view>

public class InventoryBean implements InventoryListner {
……
   private Category[] m_category;
   public HtmlAjaxOutputPanel getCategorygrid() {
    updateGUI();
    return categorygrid;
   }

   public void setCategorygrid(HtmlAjaxOutputPanel categorygrid) {
    this.categorygrid = categorygrid;
}

   private void updateGUI(){
    categorygrid.getChildren().clear();
    if (m_category != null) {
        int num = m_category.length;
        for (int index = 0; index < num; index++) {
        HtmlPanelGrid categorySubgrid =
                      JSFUtil.getLinkgrid("Bookstore_sublink" + index,
             "#{InventoryBean.category[" +index+ "].categoryLabel}",
             "#{InventoryBean.category[" +index+ "].onClickAction}");
        categorygrid.getChildren().add(categorySubgrid);
        }
    }
   }
……
}




如您所见,category.jsp 文件内的 updateGUI() 代码行就是要绑定受管 bean 中的动态元素。它清除了之前所创建的所有动态元素、基于新的数据模型创建了新的动态元素并将它们添加到预定义的父元素中。
将不同的行为绑定给不同的链接现在,让我们探讨一下该如何将不同的类别细节信息绑定到不同的类别链接。我对一个数组进行了迭代,将每个元素转变为一个 GUI            组件,并将它插入到 JSF 组件树。我的思路是把所有类别插入到一个数组,其中每个类别作为数组中的一个元素。每个元素都有一个方法来返回其类别的标签,用另一个方法来绑定单击动作。通过让每个元素都具有可以将它与其他元素区分开来的独有的类别信息,我就能确保对于每个元素均只有一个惟一的行为被绑定到 “onclick” 动作。
在               updateGUI() 内,"Bookstore_sublink" + index 是此类别链接的 ID。"#{InventoryBean.category[" + index+               "].categoryLabel}" 是此类别链接的标签。"#{InventoryBean.category[" + index+               "].onClickAction}" 是绑定到此类别链接的动作。getCategoryLabel() 方法被用来返回链接标签,onClickAction() 绑定单击动作(参见清单 6)。
清单 6. 值和动作绑定方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Category {
……
  private String category;
  private ArrayList<BookItem> bookitems;

  public String getCategoryLabel(){
    if(bookitems.size() <2){
        return bookitems.size() + " " + category;
    }else{
        return bookitems.size() + " " + category+"(s)";
    }
  }
     
public String onClickAction(){      
    HttpSession session =
               (HttpSession)JSFUtil.getFacesContext().
                         getExternalContext().getSession(true);
            session.setAttribute("CATEGORY", this);
            return "success";   
    }
……
}






欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0