日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

JSF中Tree2組件使用方法-過兒oO -JavaEye技術(shù)社區(qū)

 WindySky 2007-07-11
Tree2組件使用HTML表格將你的數(shù)據(jù)呈現(xiàn)為一個(gè)樹。這個(gè)樹是動(dòng)態(tài)的:當(dāng)用戶點(diǎn)擊它們時(shí)它們可以展開或者折疊。該組件同時(shí)支持客戶端和服務(wù)端的交互方式,在客戶端交互時(shí)使用了JavaScript。 在隨后的例子中,每次用戶的點(diǎn)擊將產(chǎn)生一個(gè)Request / Response 周期,并在新的視圖狀態(tài)(View State)中重新呈現(xiàn)新的樹結(jié)構(gòu)。

  注:在后面的例子中只有可見的(已經(jīng)展開的節(jié)點(diǎn))數(shù)據(jù)被傳送到客戶端。而在第一個(gè)例子(客戶端Tree),在每個(gè)HTML Response中,整個(gè)樹都被發(fā)送到客戶端瀏覽器。樹的每個(gè)節(jié)點(diǎn)都包含了不少的HTML代碼(假定每個(gè)節(jié)點(diǎn)200個(gè)字符,這個(gè)大小將取決于你希望在節(jié)點(diǎn)上顯示的信息的量),這些信息將被傳送到瀏覽器,其中包括了那些不可見的節(jié)點(diǎn)(沒有展開的節(jié)點(diǎn)),因?yàn)樗鼈兊囊粋€(gè)祖系節(jié)點(diǎn)被展開。如果你有一個(gè)深度有四層的樹,平均每個(gè)結(jié)點(diǎn)擁有四個(gè)子結(jié)點(diǎn),這時(shí)候你就需要傳輸10 + 102 + 103 + 104 = 11 110個(gè)節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)有200個(gè)字符,這個(gè)樹總共就有2 222 000個(gè)字符,也就是2M的數(shù)據(jù)。這個(gè)例子將向用戶說明,雖然純客戶端Tree會(huì)給客戶端帶來更好的用戶體驗(yàn),但隨之而來的帶寬問題迅速的增長。純客戶端的樹適用于小型的樹,或者在Intranet及寬帶連接中使用的中型大小的樹。對(duì)于大型的樹,或者你需要照顧到一些低帶寬的用戶的需要時(shí),你就需要使用服務(wù)端樹。你可以通過的clientSideToggle這個(gè)屬性來選擇你使用的是客戶端的樹或者服務(wù)端的樹,<t:tree2>的clientSideToggle這個(gè)屬性來選擇你使用的是客戶端的樹或者服務(wù)端的樹,<t:tree2 clientSideToggle="false" ...>將會(huì)使用服務(wù)端的樹,屬性值設(shè)為true將會(huì)使用客戶端的樹,默認(rèn)值為true。

  Backing Bean:

  Tree2組件對(duì)Backing Bean中的一個(gè)TreeModel進(jìn)行操作。通常情況,你只要把這個(gè)TreeModel綁定到這個(gè)組件上就可以了,就像這樣:

<t:tree2 value="#{myHandler.treeModel}"

  下面需要建立一個(gè)類MyHandler,在faces-config.xml中的managed bean配置成myHandler,在例子中這個(gè)類提供了一個(gè)方法getTreeModel()用于返回一個(gè)TreeModel用于表示你的數(shù)據(jù)。

public class MyHandler {
 public TreeModel getTreeModel() {
  ......
 }
}

  TreeModel實(shí)際上是對(duì)TreeNode實(shí)例進(jìn)行了一些簡單的包裝。

  TreeNode是一個(gè)接口,其中和tree2相關(guān)有四個(gè)方法:

String getType()
boolean isLeaf()
List getChildren()
int getChildCount()

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

  int getChildCount() 方法返回這個(gè)節(jié)點(diǎn)的子結(jié)點(diǎn)數(shù)量,這個(gè)方法了很容易的采用如下的方式實(shí)現(xiàn):

public final int getChildCount() {
return getChildren().size();
}

  該方法的出現(xiàn)使得對(duì)于子結(jié)點(diǎn)的延遲加載變的可行。該方法的實(shí)現(xiàn)只需要返回該節(jié)點(diǎn)的子結(jié)點(diǎn)數(shù)量,而不需要返回每個(gè)子結(jié)點(diǎn)的實(shí)例。

  boolean isLeaf() 方法在該節(jié)點(diǎn)沒有子節(jié)點(diǎn)的時(shí)候返回true。這樣,一個(gè)很直截了當(dāng)?shù)膶?shí)現(xiàn)可以這樣:

public final boolean isLeaf() {
return getChildren().isEmpty();
}

  不管你提供了什么樣的實(shí)現(xiàn),在任何時(shí)間任何情況下你都得保持getChildren().isEmpty() ==> isLeaf()。isLeaf()方法實(shí)際上控制了節(jié)點(diǎn)被怎樣呈現(xiàn):是否被當(dāng)做樹葉節(jié)點(diǎn)(不能被繼續(xù)展開)。

  String getType() 方法決定了用怎樣的方式來呈現(xiàn)這個(gè)節(jié)點(diǎn)。在 JSF 頁面中,可以在 <t:tree2> 的Tag 中嵌套facet,JSF將會(huì)選出與 getType() 方法返回值同名的 facet 用于呈現(xiàn)。如果該節(jié)點(diǎn)沒有找到相符的 facet,將會(huì)導(dǎo)致一個(gè)錯(cuò)誤,并且這個(gè)方法不會(huì)返回null。

  List getChildren() 方法返回一個(gè) List,其中包含了該節(jié)點(diǎn)下所有的 TreeNode,這就表示這些節(jié)點(diǎn)將被呈現(xiàn)為該節(jié)點(diǎn)下的子結(jié)點(diǎn)。該 List 不能包含 null,如果該 List 的大小和getChildCount()不符,將會(huì)報(bào)錯(cuò)。子結(jié)點(diǎn)將按照它們在 List 中的順序呈現(xiàn)出來。

  改變Tree中的內(nèi)容

 ?。ó?dāng)展開樹的節(jié)點(diǎn)時(shí),在后臺(tái)延遲加載)

  在郵件列表中有很多關(guān)于這項(xiàng)任務(wù)的問題和討論,我(Marcel,一個(gè) JSF 的初學(xué)者)在這里總結(jié)一下。如果你有更好的解決方案,請更新這些文字。

  在這里存在的一個(gè)問題就是我要這樣把“+”圖標(biāo)去掉:

  · <t:tree2 ... showNav="false" ...>
 
  然后再讓文件夾圖標(biāo)(代表包含子節(jié)點(diǎn)的節(jié)點(diǎn))變的可點(diǎn)擊:

  · <h:commandLink action="#{t.toggleExpanded}" actionListener="#{navigationBacker.processAction}">

  然后在 Java 代碼中接受鼠標(biāo)點(diǎn)擊的事件。在 NavigationBacker.java 文件中的processAction(ActionEvent e) 方法里,我從 EJB3-persistency 中加載子結(jié)點(diǎn)的數(shù)據(jù)。

  不好的是“+”圖標(biāo)變的不可見,但是我現(xiàn)在沒有辦法獲取點(diǎn)擊“+”圖標(biāo)的事件。

  看起來在org.apache.myfaces.custom.tree2.HtmlTree.java這個(gè)文件里是通過注冊了_expandControl = new HtmlCommandLink(); 從內(nèi)部獲取“+”的點(diǎn)擊事件,但是我現(xiàn)在沒有辦法從我的代碼中接受到這一事件。

  為了導(dǎo)航,我使用了含有entries的TreeNode.getIdentifier() (參見:#{node.identifier}),看起來就是這個(gè)樣子:

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

  這代表了后臺(tái)數(shù)據(jù)庫表的主鍵(我還沒有找到一個(gè)更好的解決方案用于導(dǎo)航)

  程序代碼如下:

  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

/** *//**
* 攔截節(jié)點(diǎn)被展開的事件,并加載額外的數(shù)據(jù)
* @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); // 沒有顯示
  }
 }
}
}

/** *//** 把當(dāng)前car_id下的Person子結(jié)點(diǎn)加入導(dǎo)航中 */
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 用于多種用途。

/** *//**
* 當(dāng) JSF 組件 h:commandLink 包含有 f:param 成員, 這些 name-value 對(duì)被放到
* request 參數(shù)表中供后面的action handler使用。不幸的是,這樣的用法不能用在
* h:commandButton上。我們沒有辦法把通過 button 來傳遞這些參數(shù)。
*
* 因?yàn)?Action Listeners 可以保證在 Action 方法前被執(zhí)行到,所以 Action Listeners
* 可以調(diào)用該方法更新 Action 方法所需要的任何上下文。
*
* From http://cvs./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 中進(jìn)行配置。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請遵守用戶 評(píng)論公約

    類似文章 更多