默认情况下,只有点击树节点的最左边的三角图标时才能展开或收缩子节点,点击树节点文字时不会展开或收缩子节点。
我们可以通过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
http://maping930883.blogspot.com/2012/06/adf135tree.html