以前在公司,平臺組已經把組件都給我們開發好了,對于界面沒有花太多的時間研究。近日想自己做個小系統,還是用比較擅長的JSF+Hibernate+Spring。考慮Facelet的模板功能,這次想嘗試一下。結果,一個Tree2就把我納悶了好一會。
從網上找了篇文章,試著依樣畫葫蘆,做了模板頁,分top,left,content三塊布局,left自然就是tree2菜單了。
首先看一下模板頁:
template.xthml
1 <div id="left">
2 <ui:insert name="left">
3 <ui:include src="leftmenu.xhtml"></ui:include>
4 </ui:insert>
5 </div>
6 <div id="content" class="left_content">
7 <ui:insert name="content">Content</ui:insert>
8 </div>
其中左邊菜單:
leftmenu.xhtml
1 <t:tree2 id="serverTree" value="#{calendarBean.treeData}" var="node" varNodeToggler="t" clientSideToggle="false" showRootNode="true">
2 

3 <f:facet name="document">
4 <h:panelGroup>
5 <h:commandLink immediate="true" styleClass="#{t.nodeSelected ? 'documentSelected':'document'}" action="link_page" actionListener="#{t.setNodeSelected}">
6 <t:graphicImage value="/images/document.png" border="0"/>
7 <h:outputText value="#{node.description}"/>
8 <f:param name="docNum" value="#{node.identifier}"/>
9 </h:commandLink>
10 </h:panelGroup>
11 </f:facet>
12 </t:tree2>
其中backingBean代碼如下,配置有效范圍為session
public class calendarBean {
private TreeData treeData;
private Date secondDate;
public Date getSecondDate() {
return secondDate;
}
public void setSecondDate(Date secondDate) {
this.secondDate = secondDate;
}
public TreeData getTreeDate() {
if (null == treeData) {
TreeNode treeData = new TreeNodeBase("foo-folder", "Inbox", false);
......
}
return treeData;
}
......
}
這里為了方便測試,故意把commandLink的action指向link_page導航,link_page配置為:
1 <navigation-rule>
2 <from-view-id>/treeSample2.xhtml</from-view-id>
3 <navigation-case>
4 <from-outcome>link_page</from-outcome>
5 <to-view-id>/treeSample2link.xhtml</to-view-id>
6 </navigation-case>
7 </navigation-rule>
treeSample2.xhtml和treeSample2link.xhtml分別為兩個使用了template.xhtml模板的頁面,顯然它們都用到了菜單。
運行后,首先打開treeSample.xhtml,非常成功,菜單出來了,而且由于使用了Server端樹,每次打開子節點,都會提交到服務器,頁面刷新后,除了正在操作的節點,其他節點也都保持原來的狀態。

但是,當我點擊節點,跳轉到treeSample2link.xhtml時,問題出來,所有節點都折疊起來,而并沒有保持我原來頁面的狀態。這說明從一個頁面跳轉到另一個頁面時,節點狀態并沒有被傳遞過去。
有些想不明白,既然backingbean是session的,為什么沒有記錄節點的狀態呢?網上搜了些資料,很少有提到關于狀態的。myface的wiki中似乎也找不到類似的問題。無奈之下,只能直接看tree2的代碼,終于發現了問題所在。原來我有個TreeState接口存儲節點狀態的,而它又是被set到treeModel的,而我的代碼中只使用了treeData,沒有給它包裝成treeModel。Tree2中提供了treeModel的一個實現treeModelBase,直接使用就可以了。于是乎,改一下代碼:
1 public class calendarBean {
2
3 private TreeModel personTreeModel;
4
5 public TreeModel getPersonTreeModel() {
6 if (null == personTreeModel) {
7 TreeNode treeData = new TreeNodeBase("foo-folder", "Inbox", false);
8 

9 personTreeModel = new TreeModelBase(treeData);
10 }
11 return personTreeModel;
12 }
13
14 }
改一下綁定:
1 <t:tree2 id="serverTree" value="#{calendarBean.persontreeModel}" 

測試一下,果然,無論怎么鏈接,依然保持良好的狀態,呵呵。