2012年6月12日星期二

ADF_135:Tree组件使用指南之五:点击树节点文字展开或收缩其子节点

运行环境:JDeveloper 11.1.2.2.0 + Oracle Database 10g Express Edition 10.2.0.1。

默认情况下,只有点击树节点的最左边的三角图标时才能展开或收缩子节点,点击树节点文字时不会展开或收缩子节点。
我们可以通过af:clientListener来实现点击树节点文字时不会展开或收缩子节点功能。

重点步骤说明:

1. 为Tree组件增加ClientListener
Tree组件上发生click事件时将会调用JavaScript函数:expandDiscloseNode。

<af:tree value="#{bindings.DepartmentsView1.treeModel}" var="node"
selectionListener="#{myBackingBean.treeSelectionListener}" rowSelection="single" id="t1">
<f:facet name="nodeStamp">
<af:outputText value="#{node}" id="ot1"/>
</f:facet>
<af:clientListener method="expandDiscloseNode" type="click"/>
</af:tree>


2. JavaScript函数:expandDiscloseNode
基本逻辑:找到当前选择的节点(只选择第一个),如果该节点处于展开状态,那么收缩;反之则展开。

function expandDiscloseNode(event) {
var tree = event.getSource();
var rwKeySet = tree.getSelectedRowKeys();
var firstRowKey;
for (rowKey in rwKeySet) {
firstRowKey = rowKey;
}
if (tree.isPathExpanded(firstRowKey)) {
tree.setDisclosedRowKey(firstRowKey, false);
}
else {
tree.setDisclosedRowKey(firstRowKey, true);
}
}


3. 运行
直接点击节点文字,就可以展开或收缩其子节点。

4. 常见错误
经常出现的错误是找不到JavaScript函数,这时要仔细检查JavaScript函数文件的位置。
并且要把该文件使用af:resource放到af:document和af:message之间。
<af:document title="tree_selection_listener.jsf" id="d1">
<af:resource type="javascript" source="resources/js/tree_function.js"/>
<af:messages id="m1"/>

5. 在页面初始化时,展开指定的节点
默认情况下,Tree组件只展开第一层根节点,实际场景中可能希望页面初始化时能够展开指定的节点。
我们可以考虑使用JSF LifeCycle在页面初始化时做一些事情,比如展开两级节点:

实现原理和步骤如下:
(1)在Managed Bean中增加一个方法:beforeRenderResponse(PhaseEvent phaseEvent)

public void beforeRenderResponse(PhaseEvent phaseEvent) {
if (phaseEvent.getPhaseId() == PhaseId.RENDER_RESPONSE) {
FacesContext fctx = FacesContext.getCurrentInstance();
AdfFacesContext adfFacesContext = AdfFacesContext.getCurrentInstance();

boolean isInitialRender = adfFacesContext.isInitialRender();
if (isInitialRender) {
UIViewRoot viewRoot = fctx.getViewRoot();
UIComponent tree = viewRoot.findComponent("t1");
if (tree != null) {
CollectionModel model = (CollectionModel)((RichTree)tree).getValue();
JUCtrlHierBinding treeBinding = (JUCtrlHierBinding)model.getWrappedData();
JUCtrlHierNodeBinding rootNode = treeBinding.getRootNodeBinding();
RowKeySet rks = (((RichTree)tree).getDisclosedRowKeys());
if (rks == null) {
rks = new RowKeySetImpl();
}
if (rks.getSize() == 0) {
List firstLevelChildren = rootNode.getChildren();
for (JUCtrlHierNodeBinding node : firstLevelChildren) {
ArrayList l = new ArrayList();
l.add(node.getRowKey());
rks.add(l);
}
((RichTree)tree).setDisclosedRowKeys(rks);
}
}
}
}
}

在RENDER_RESPONSE之前,并且如果是初次请求该页面,那么找到Tree组件,把第2级节点加到DisclosedRowKeys中。
AdfFacesContext提供了三个方法来判断页面的状态:isInitialRender 是否是初次请求;isPartialRequest 是否是局部刷新请求;isPostback 是否是提交表单后的返回请求。
(2)在页面中的f:view中设置beforePhase,指向方法:beforeRenderResponse。
<f:view xmlns:f="http://java.sun.com/jsf/core" xmlns:af="http://xmlns.oracle.com/adf/faces/rich"
beforePhase="#{myBackingBean.beforeRenderResponse}">

Project 下载:ADF_Tree_SelectionListener(3).7z

参考文献:
1. http://www.oracle.com/technetwork/developer-tools/adf/learnmore/20-expand-tree-node-from-label-169156.pdf
2. http://www.oracle.com/technetwork/developer-tools/adf/learnmore/21-expand-tree-on-initial-render-169158.pdf

没有评论: