改變Tree中的內(nèi)容
(當(dāng)展開(kāi)樹(shù)的節(jié)點(diǎn)時(shí),在后臺(tái)延遲加載)
在郵件列表中有很多關(guān)于這項(xiàng)任務(wù)的問(wèn)題和討論,我(Marcel,一個(gè) JSF 的初學(xué)者)在這里總結(jié)一下。如果你有更好的解決方案,請(qǐng)更新這些文字。
在這里存在的一個(gè)問(wèn)題就是我要這樣把“+”圖標(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)變的不可見(jiàn),但是我現(xiàn)在沒(méi)有辦法獲取點(diǎn)擊“+”圖標(biāo)的事件。
看起來(lái)在org.apache.myfaces.custom.tree2.HtmlTree.java這個(gè)文件里是通過(guò)注冊(cè)了_expandControl = new HtmlCommandLink(); 從內(nèi)部獲取“+”的點(diǎn)擊事件,但是我現(xiàn)在沒(méi)有辦法從我的代碼中接受到這一事件。
為了導(dǎo)航,我使用了含有entries的TreeNode.getIdentifier() (參見(jiàn):#{node.identifier}),看起來(lái)就是這個(gè)樣子:
· db_id="car_id=7,person_id=2"
這代表了后臺(tái)數(shù)據(jù)庫(kù)表的主鍵(我還沒(méi)有找到一個(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)被展開(kāi)的事件,并加載額外的數(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" 拆分開(kāi)
this.car_id = map.get("car_id");

if (this.car_id != null)
{
appendPersonsNodes(node); // 參見(jiàn)下面的例子
}
this.person_id = map.get("person_id");

if (this.person_id != null)
{
appendLicensesNodes(node); // 沒(méi)有顯示
}
}
}
}


/** *//** 把當(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上。我們沒(méi)有辦法把通過(guò) button 來(lái)傳遞這些參數(shù)。
*
* 因?yàn)?nbsp;Action Listeners 可以保證在 Action 方法前被執(zhí)行到,所以 Action Listeners
* 可以調(diào)用該方法更新 Action 方法所需要的任何上下文。
*
* From http://cvs.sakaiproject.org/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)行配置。
很多朋友和我交流了一些有關(guān) Tree2 的問(wèn)題,我把一些大家經(jīng)常碰到的問(wèn)題拿出來(lái),希望剛開(kāi)始學(xué)習(xí)的朋友能夠避免再犯一些這樣的錯(cuò)誤。
1.首先就是關(guān)于 myfaces 包的問(wèn)題,Myfaces 1.1.1 release 版本的 Tree2 是有 bug 的,大概在十一月份的時(shí)候修正了大部分問(wèn)題,但是由于這以后并沒(méi)有 release 版本出來(lái),所以大家可以使用一些較新一點(diǎn)的 Nightly Build,可以去這里找找http://cvs.apache.org/builds/myfaces/nightly/ ,不過(guò)從元旦后似乎改用了 Maven 后還沒(méi)有一個(gè) Build 出來(lái),我手上有一個(gè)12.30 Build的版本,如果需要的話可以和我聯(lián)系。因?yàn)檫@些 Nightly Build 不確定可能還會(huì)有其它的一些問(wèn)題,所以用的時(shí)候要慎重一點(diǎn)。
2. 有些朋友就直接把代碼貼上去用,會(huì)碰到一些諸如點(diǎn)擊沒(méi)有反應(yīng)或者圖標(biāo)顯示不出來(lái)的問(wèn)題,很多時(shí)候是因?yàn)闆](méi)有加上MyFaces' Extensions Filter,相關(guān)的內(nèi)容可以參考我前面寫的http://www.aygfsteel.com/steady/archive/2005/11/17/20170.html。
希望這兩篇介紹 Tree2 的文章能給大家一些新的認(rèn)識(shí),今后也會(huì)努力拿出更多更好的東西來(lái)和大家分享。
posted on 2006-01-13 19:28
steady 閱讀(3088)
評(píng)論(1) 編輯 收藏 所屬分類:
JSF & Myfaces