国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > 綜合 > 正文

深入討論JSF中Tree2組件使用方法

2024-07-21 02:14:54
字體:
來源:轉載
供稿:網友

  tree2組件使用html表格將你的數據呈現為一個樹。這個樹是動態的:當用戶點擊它們時它們可以展開或者折疊。該組件同時支持客戶端和服務端的交互方式,在客戶端交互時使用了javascript。在隨后的例子中,每次用戶的點擊將產生一個request / response 周期,并在新的視圖狀態(view state)中重新呈現新的樹結構。

  注:在后面的例子中只有可見的(已經展開的節點)數據被傳送到客戶端。而在第一個例子(客戶端tree),在每個html response中,整個樹都被發送到客戶端瀏覽器。樹的每個節點都包含了不少的html代碼(假定每個節點200個字符,這個大小將取決于你希望在節點上顯示的信息的量),這些信息將被傳送到瀏覽器,其中包括了那些不可見的節點(沒有展開的節點),因為它們的一個祖系節點被展開。如果你有一個深度有四層的樹,平均每個結點擁有四個子結點,這時候你就需要傳輸10 + 102 + 103 + 104 = 11 110個節點,每個節點有200個字符,這個樹總共就有2 222 000個字符,也就是2m的數據。這個例子將向用戶說明,雖然純客戶端tree會給客戶端帶來更好的用戶體驗,但隨之而來的帶寬問題迅速的增長。純客戶端的樹適用于小型的樹,或者在intranet及寬帶連接中使用的中型大小的樹。對于大型的樹,或者你需要照顧到一些低帶寬的用戶的需要時,你就需要使用服務端樹。你可以通過的clientsidetoggle這個屬性來選擇你使用的是客戶端的樹或者服務端的樹,<t:tree2>的clientsidetoggle這個屬性來選擇你使用的是客戶端的樹或者服務端的樹,<t:tree2 clientsidetoggle="false" ...>將會使用服務端的樹,屬性值設為true將會使用客戶端的樹,默認值為true。

  backing bean:

  tree2組件對backing bean中的一個treemodel進行操作。通常情況,你只要把這個treemodel綁定到這個組件上就可以了,就像這樣:

<t:tree2 value="#{myhandler.treemodel}"

  下面需要建立一個類myhandler,在faces-config.xml中的managed bean配置成myhandler,在例子中這個類提供了一個方法gettreemodel()用于返回一個treemodel用于表示你的數據。

public class myhandler {
 public treemodel gettreemodel() {
  ......
 }
}

  treemodel實際上是對treenode實例進行了一些簡單的包裝。

  treenode是一個接口,其中和tree2相關有四個方法:

string gettype()
boolean isleaf()
list getchildren()
int getchildcount()

  其它方法都沒有什么用處了,可能會在今后的版本中取消。它們要求開發者在開發backing bean中做一些并不必要的操作。

  int getchildcount() 方法返回這個節點的子結點數量,這個方法了很容易的采用如下的方式實現:

public final int getchildcount() {
return getchildren().size();
}

  該方法的出現使得對于子結點的延遲加載變的可行。該方法的實現只需要返回該節點的子結點數量,而不需要返回每個子結點的實例。

  boolean isleaf() 方法在該節點沒有子節點的時候返回true。這樣,一個很直截了當的實現可以這樣:

public final boolean isleaf() {
return getchildren().isempty();
}

  不管你提供了什么樣的實現,在任何時間任何情況下你都得保持getchildren().isempty() ==> isleaf()。isleaf()方法實際上控制了節點被怎樣呈現:是否被當做樹葉節點(不能被繼續展開)。

  string gettype() 方法決定了用怎樣的方式來呈現這個節點。在 jsf 頁面中,可以在 <t:tree2> 的tag 中嵌套facet,jsf將會選出與 gettype() 方法返回值同名的 facet 用于呈現。如果該節點沒有找到相符的 facet,將會導致一個錯誤,并且這個方法不會返回null。

  list getchildren() 方法返回一個 list,其中包含了該節點下所有的 treenode,這就表示這些節點將被呈現為該節點下的子結點。該 list 不能包含 null,如果該 list 的大小和getchildcount()不符,將會報錯。子結點將按照它們在 list 中的順序呈現出來。

  改變tree中的內容

  (當展開樹的節點時,在后臺延遲加載)

  在郵件列表中有很多關于這項任務的問題和討論,我(marcel,一個 jsf 的初學者)在這里總結一下。如果你有更好的解決方案,請更新這些文字。

  在這里存在的一個問題就是我要這樣把“+”圖標去掉:

  · <t:tree2 ... shownav="false" ...>
 
  然后再讓文件夾圖標(代表包含子節點的節點)變的可點擊:

  · <h:commandlink action="#{t.toggleexpanded}" actionlistener="#{navigationbacker.processaction}">

  然后在 java 代碼中接受鼠標點擊的事件。在 navigationbacker.java 文件中的processaction(actionevent e) 方法里,我從 ejb3-persistency 中加載子結點的數據。

  不好的是“+”圖標變的不可見,但是我現在沒有辦法獲取點擊“+”圖標的事件。

  看起來在org.apache.myfaces.custom.tree2.htmltree.java這個文件里是通過注冊了_expandcontrol = new htmlcommandlink(); 從內部獲取“+”的點擊事件,但是我現在沒有辦法從我的代碼中接受到這一事件。

  為了導航,我使用了含有entries的treenode.getidentifier() (參見:#{node.identifier}),看起來就是這個樣子:

  · db_id="car_id=7,person_id=2"

  這代表了后臺數據庫表的主鍵(我還沒有找到一個更好的解決方案用于導航)

  程序代碼如下:

  navigation.jsp

<t:tree2 id="servertree" value="#{navigationbacker.treedata}"
var="node" varnodetoggler="t" clientsidetoggle="false" shownav="false"
showrootnode="false">
<f:facet name="project-folder">
<h:panelgroup>
<h:commandlink action="#{t.toggleexpanded}" actionlistener="#{navigationbacker.processaction}">
<t:graphicimage value="/images/yellow-folder-open.png"
rendered="#{t.nodeexpanded}" border="0" />
<t:graphicimage value="/images/yellow-folder-closed.png"
rendered="#{!t.nodeexpanded}" border="0" />
</h:commandlink>
<h:commandlink action="#{navigationbacker.toviewid}"
styleclass="#{t.nodeselected ? 'documentselected':'document'}"
actionlistener="#{navigationbacker.nodeclicked}"
value="#{node.description}" immediate="true">
<f:param name="db_id" value="#{node.identifier}" />

</h:commandlink>
<h:outputtext value=" (#{node.childcount})" styleclass="childcount"
rendered="#{!empty node.children}" />
</h:panelgroup>
</f:facet>
<f:facet name="person-folder">
<h:panelgroup>

  navigationbacker.java

/** *//**
* 攔截節點被展開的事件,并加載額外的數據
* @param event
* @throws abortprocessingexception
*/
public void processaction(actionevent event) throws abortprocessingexception {
system.out.println("entering processaction()");
uicomponent component = (uicomponent) event.getsource();
while (!(component != null && component instanceof htmltree)) {
 component = component.getparent();
}
if (component != null) {
 htmltree tree = (htmltree) component;
 treenodebase node = (treenodebase) tree.getnode();
 if (!tree.isnodeexpanded() && node.getchildren().size() == 0) {
  map<string, string> map = splitkeyvalues(node.getidentifier()); // 一些輔助代碼,用于將 "car_id=7" 或 "car_id=7&person_id=12" 拆分開
  this.car_id = map.get("car_id");
  if (this.car_id != null) {
   appendpersonsnodes(node); // 參見下面的例子
  }
  this.person_id = map.get("person_id");
  if (this.person_id != null) {
   appendlicensesnodes(node); // 沒有顯示
  }
 }
}
}

/** *//** 把當前car_id下的person子結點加入導航中 */
private void appendpersonsnodes(treenodebase cardetailnode) {
 variableresolver resolver = facescontext.getcurrentinstance().getapplication().getvariableresolver();
 personstable personstable = (personstable) resolver.resolvevariable(facescontext.getcurrentinstance(),
"personstable");
 list<person> personslist = personstable.getcarpersons();
 for (person o : personslist) {
  list<treenodebase> list = cardetailnode.getchildren();
  list.add(new treenodebase("person-folder", o.getdescription(),"person_id=" + o.getpersonid(), true));
 }
 system.out.println("navigationbacker fetched " + personslist.size() + " persons for carid=" + this.car_id);
}

  這里有一段輔助代碼用于從 h:commandlink 中獲取 f:param 用于多種用途。

/** *//**
* 當 jsf 組件 h:commandlink 包含有 f:param 成員, 這些 name-value 對被放到
* request 參數表中供后面的action handler使用。不幸的是,這樣的用法不能用在
* h:commandbutton上。我們沒有辦法把通過 button 來傳遞這些參數。
*
* 因為 action listeners 可以保證在 action 方法前被執行到,所以 action listeners
* 可以調用該方法更新 action 方法所需要的任何上下文。
*
* from http://cvs.sakaiproject.org/release/2.0.0/
* sakai2/gradebook/tool/src/java/org/sakaiproject/tool/gradebook/jsf/facesutil.java
* educational community license version 1.0
*/
public static final map geteventparametermap(facesevent event) {
 map<string, string> parametermap = new hashmap<string, string>();
 list children = event.getcomponent().getchildren();
 for (iterator iter = children.iterator(); iter.hasnext();) {
  object next = iter.next();
  if (next instanceof uiparameter) {
   uiparameter param = (uiparameter) next;
   parametermap.put(param.getname(), "" + param.getvalue());
  }
 }
 //system.out.println("parametermap=" + parametermap);
 return parametermap;
}

  注:在上面的例子里,backing bean都存放于 session 作用域里,可以在web-inf/examples-config.xml 中進行配置。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 蒙自县| 凤阳县| 彭水| 华坪县| 肃宁县| 休宁县| 四平市| 恩平市| 乌审旗| 钟祥市| 绥宁县| 台中县| 无为县| 古丈县| 黄浦区| 扎兰屯市| 岳普湖县| 军事| 武胜县| 易门县| 景宁| 汉中市| 伊宁县| 龙口市| 天镇县| 重庆市| 鹰潭市| 定安县| 措勤县| 白城市| 高青县| 吉安市| 上犹县| 调兵山市| 桂平市| 嫩江县| SHOW| 承德市| 吴川市| 家居| 朔州市|