以前在公司,平台组已经把组件都给我们开发好了,对于界面没有花太多的时间研究。近日想自己做个小系统,还是用比较擅长的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}"
测试一下,果然,无论怎么链接,依然保持良好的状态,呵呵。