jsf树型菜单.docx

上传人:b****8 文档编号:9916831 上传时间:2023-02-07 格式:DOCX 页数:12 大小:22.02KB
下载 相关 举报
jsf树型菜单.docx_第1页
第1页 / 共12页
jsf树型菜单.docx_第2页
第2页 / 共12页
jsf树型菜单.docx_第3页
第3页 / 共12页
jsf树型菜单.docx_第4页
第4页 / 共12页
jsf树型菜单.docx_第5页
第5页 / 共12页
点击查看更多>>
下载资源
资源描述

jsf树型菜单.docx

《jsf树型菜单.docx》由会员分享,可在线阅读,更多相关《jsf树型菜单.docx(12页珍藏版)》请在冰豆网上搜索。

jsf树型菜单.docx

jsf树型菜单

使用JSF中的

Sidebar>

Sidebar>实现动态加载菜单,其中bar.getChildren().add(aSidebarGroup);是实现动态加载首节点,HtmlSidebarGroupaSidebarGroup=(HtmlSidebarGroup)application.createComponent(HtmlSidebarGroup.COMPONENT_TYPE);

    aSidebarGroup.setText(boardName);

    aSidebarGroup.setExpanded(true);

    aSidebarGroup.setId(viewRoot.createUniqueId());实现加载该节点下的子节点,非常方便。

privateSidebarbuildSideBar(Sidebarbar)

 {

  booleanisInitialised=bar.getAttributes().get("IS_INITIALISED")!

=null;

  

  if(!

isInitialised){

   //GetareferencetotheJSFApplication,

   //weneedittocreatevaluebindingslater-on

   Applicationapplication=FacesContext.getCurrentInstance().getApplication();

   UIViewRootviewRoot=FacesContext.getCurrentInstance().getViewRoot();

   

   /*CreateInfragisticsSidebarGroup*/

   //SettheSidebar'swidthandheight

   bar.getAttributes().put("style","width:

155px;height:

590px;");

   //CreateSidebarGroup

   Listlist=this.getBoardNameForMenu();

   for(inti=0;i

   {

    Object[]row=(Object[])list.get(i);

   //Object[]row=(Object[])list.listIterator().next();

    StringboardId=String.valueOf(row[0]);

    StringboardName=String.valueOf(row[1]);

    StringparentId=String.valueOf(row[2]);

    HtmlSidebarGroupaSidebarGroup=(HtmlSidebarGroup)application.createComponent(HtmlSidebarGroup.COMPONENT_TYPE);

    aSidebarGroup.setText(boardName);

    aSidebarGroup.setExpanded(true);

    aSidebarGroup.setId(viewRoot.createUniqueId());

   

    //AddthenewlycreatedSidebarGrouptotheSidebar'schildrenlist

    bar.getChildren().add(aSidebarGroup);

    

    Listls=this.getBoardNameForMenuBar(Integer.parseInt(boardId));

    if(ls.size()!

=0)

    {

     for(intj=0;j

     {

      Object[]row1=(Object[])ls.get(j);

      Stringboardid=String.valueOf(row1[0]);

      Stringboardname=String.valueOf(row1[1]);

      //HtmlSidebarGroupaSidebarGroup=(HtmlSidebarGroup)application.createComponent(HtmlSidebarGroup.COMPONENT_TYPE);

      HtmlLinkaLink1=(HtmlLink)application.createComponent(HtmlLink.COMPONENT_TYPE);

      aLink1.setId(viewRoot.createUniqueId());

      //aSidebarGroup.setText(sidebarGroupNameStr);

      //aSidebarGroup.setExpanded(true);

      //aSidebarGroup.setId(viewRoot.createUniqueId());

      //aLink1.setId(parentId);

      aLink1.setUrl("/pages/bbs/visitor/topic/topicforboard.jsf?

boardid="+boardid+"");

      aLink1.setValue(boardname);

      aSidebarGroup.getChildren().add(aLink1);

     }

    }

    

   }

深入讨论JSF中Tree2组件使用方法

2006-01-1608:

48作者:

steady出处:

Java博客责任编辑:

方舟

  Tree2组件使用HTML表格将你的数据呈现为一个树。

这个树是动态的:

当用户点击它们时它们可以展开或者折叠。

该组件同时支持客户端和服务端的交互方式,在客户端交互时使用了JavaScript。

在随后的例子中,每次用户的点击将产生一个Request/Response周期,并在新的视图状态(ViewState)中重新呈现新的树结构。

  注:

在后面的例子中只有可见的(已经展开的节点)数据被传送到客户端。

而在第一个例子(客户端Tree),在每个HTMLResponse中,整个树都被发送到客户端浏览器。

树的每个节点都包含了不少的HTML代码(假定每个节点200个字符,这个大小将取决于你希望在节点上显示的信息的量),这些信息将被传送到浏览器,其中包括了那些不可见的节点(没有展开的节点),因为它们的一个祖系节点被展开。

如果你有一个深度有四层的树,平均每个结点拥有四个子结点,这时候你就需要传输10+102+103+104=11110个节点,每个节点有200个字符,这个树总共就有2222000个字符,也就是2M的数据。

这个例子将向用户说明,虽然纯客户端Tree会给客户端带来更好的用户体验,但随之而来的带宽问题迅速的增长。

纯客户端的树适用于小型的树,或者在Intranet及宽带连接中使用的中型大小的树。

对于大型的树,或者你需要照顾到一些低带宽的用户的需要时,你就需要使用服务端树。

你可以通过的clientSideToggle这个属性来选择你使用的是客户端的树或者服务端的树,<t:

tree2>的clientSideToggle这个属性来选择你使用的是客户端的树或者服务端的树,<t:

tree2clientSideToggle="false"...>将会使用服务端的树,属性值设为true将会使用客户端的树,默认值为true。

  BackingBean:

  Tree2组件对BackingBean中的一个TreeModel进行操作。

通常情况,你只要把这个TreeModel绑定到这个组件上就可以了,就像这样:

<t:

tree2value="#{myHandler.treeModel}"

  下面需要建立一个类MyHandler,在faces-config.xml中的managedbean配置成myHandler,在例子中这个类提供了一个方法getTreeModel()用于返回一个TreeModel用于表示你的数据。

publicclassMyHandler{

 publicTreeModelgetTreeModel(){

  ......

 }

}

  TreeModel实际上是对TreeNode实例进行了一些简单的包装。

  TreeNode是一个接口,其中和tree2相关有四个方法:

StringgetType()

booleanisLeaf()

ListgetChildren()

intgetChildCount()

  其它方法都没有什么用处了,可能会在今后的版本中取消。

它们要求开发者在开发backingbean中做一些并不必要的操作。

  intgetChildCount()方法返回这个节点的子结点数量,这个方法了很容易的采用如下的方式实现:

publicfinalintgetChildCount(){

returngetChildren().size();

}

  该方法的出现使得对于子结点的延迟加载变的可行。

该方法的实现只需要返回该节点的子结点数量,而不需要返回每个子结点的实例。

  booleanisLeaf()方法在该节点没有子节点的时候返回true。

这样,一个很直截了当的实现可以这样:

publicfinalbooleanisLeaf(){

returngetChildren().isEmpty();

}

  不管你提供了什么样的实现,在任何时间任何情况下你都得保持getChildren().isEmpty()==>isLeaf()。

isLeaf()方法实际上控制了节点被怎样呈现:

是否被当做树叶节点(不能被继续展开)。

  StringgetType()方法决定了用怎样的方式来呈现这个节点。

在JSF页面中,可以在<t:

tree2>的Tag中嵌套facet,JSF将会选出与getType()方法返回值同名的facet用于呈现。

如果该节点没有找到相符的facet,将会导致一个错误,并且这个方法不会返回null。

  ListgetChildren()方法返回一个List,其中包含了该节点下所有的TreeNode,这就表示这些节点将被呈现为该节点下的子结点。

该List不能包含null,如果该List的大小和getChildCount()不符,将会报错。

子结点将按照它们在List中的顺序呈现出来。

  改变Tree中的内容

  (当展开树的节点时,在后台延迟加载)

  在邮件列表中有很多关于这项任务的问题和讨论,我(Marcel,一个JSF的初学者)在这里总结一下。

如果你有更好的解决方案,请更新这些文字。

  在这里存在的一个问题就是我要这样把“+”图标去掉:

  ·<t:

tree2...showNav="false"...>

 

  然后再让文件夹图标(代表包含子节点的节点)变的可点击:

  ·<h:

commandLinkaction="#{t.toggleExpanded}"actionListener="#{navigationBacker.processAction}">

  然后在Java代码中接受鼠标点击的事件。

在NavigationBacker.java文件中的processAction(ActionEvente)方法里,我从EJB3-persistency中加载子结点的数据。

  不好的是“+”图标变的不可见,但是我现在没有办法获取点击“+”图标的事件。

  看起来在org.apache.myfaces.custom.tree2.HtmlTree.java这个文件里是通过注册了_expandControl=newHtmlCommandLink();从内部获取“+”的点击事件,但是我现在没有办法从我的代码中接受到这一事件。

  为了导航,我使用了含有entries的TreeNode.getIdentifier()(参见:

#{node.identifier}),看起来就是这个样子:

  ·db_id="car_id=7,person_id=2"

  这代表了后台数据库表的主键(我还没有找到一个更好的解决方案用于导航)

  程序代码如下:

  navigation.jsp

<t:

tree2id="serverTree"value="#{navigationBacker.treeData}"

var="node"varNodeToggler="t"clientSideToggle="false"showNav="false"

showRootNode="false">

<f:

facetname="project-folder">

<h:

panelGroup>

<h:

commandLinkaction="#{t.toggleExpanded}"actionListener="#{navigationBacker.processAction}">

<t:

graphicImagevalue="/images/yellow-folder-open.png"

rendered="#{t.nodeExpanded}"border="0"/>

<t:

graphicImagevalue="/images/yellow-folder-closed.png"

rendered="#{!

t.nodeExpanded}"border="0"/>

</h:

commandLink>

<h:

commandLinkaction="#{navigationBacker.toViewId}"

styleClass="#{t.nodeSelected?

'documentSelected':

'document'}"

actionListener="#{navigationBacker.nodeClicked}"

value="#{node.description}"immediate="true">

<f:

paramname="db_id"value="#{node.identifier}"/>

</h:

commandLink>

<h:

outputTextvalue="(#{node.childCount})"styleClass="childCount"

rendered="#{!

emptynode.children}"/>

</h:

panelGroup>

</f:

facet>

<f:

facetname="person-folder">

<h:

panelGroup>

  NavigationBacker.java

/***//**

*拦截节点被展开的事件,并加载额外的数据

*@paramevent

*@throwsAbortProcessingException

*/

publicvoidprocessAction(ActionEventevent)throwsAbortProcessingException{

System.out.println("EnteringprocessAction()");

UIComponentcomponent=(UIComponent)event.getSource();

while(!

(component!

=null&&componentinstanceofHtmlTree)){

 component=component.getParent();

}

if(component!

=null){

 HtmlTreetree=(HtmlTree)component;

 TreeNodeBasenode=(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"拆分开

  this.car_id=map.get("car_id");

  if(this.car_id!

=null){

   appendPersonsNodes(node);//参见下面的例子

  }

  this.person_id=map.get("person_id");

  if(this.person_id!

=null){

   appendLicensesNodes(node);//没有显示

  }

 }

}

}

/***//**把当前car_id下的Person子结点加入导航中*/

privatevoidappendPersonsNodes(TreeNodeBasecarDetailNode){

 VariableResolverresolver=FacesContext.getCurrentInstance().getApplication().getVariableResolver();

 PersonsTablepersonsTable=(PersonsTable)resolver.resolveVariable(FacesContext.getCurrentInstance(),

"personsTable");

 List<Person>personsList=personsTable.getCarPersons();

 for(Persono:

personsList){

  List<TreeNodeBase>list=carDetailNode.getChildren();

  list.add(newTreeNodeBase("person-folder",o.getDescription(),"person_id="+o.getPersonId(),true));

 }

 System.out.println("NavigationBackerfetched"+personsList.size()+"PersonsforcarId="+this.car_id);

}

  这里有一段辅助代码用于从h:

commandLink中获取f:

param用于多种用途。

/***//**

*当JSF组件h:

commandLink包含有f:

param成员,这些name-value对被放到

*request参数表中供后面的actionhandler使用。

不幸的是,这样的用法不能用在

*h:

commandButton上。

我们没有办法把通过button来传递这些参数。

*

*因为ActionListeners可以保证在Action方法前被执行到,所以ActionListeners

*可以调用该方法更新Action方法所需要的任何上下文。

*

*Fromhttp:

//cvs.sakaiproject.org/release/2.0.0/

*sakai2/gradebook/tool/src/java/org/sakaiproject/tool/gradebook/jsf/FacesUtil.java

*EducationalCommunityLicenseVersion1.0

*/

publicstaticfinalMapgetEventParameterMap(FacesEventevent){

 Map<String,String>parameterMap=newHashMap<String,String>();

 Listchildren=event.getComponent().getChildren();

 for(Iteratoriter=children.iterator();iter.hasNext();){

  Objectnext=iter.next();

  if(nextinstanceofUIParameter){

   UIParameterparam=(UIParameter)next;

   parameterMap.put(param.getName(),""+param.getValue());

  }

 }

 //System.out.println("parameterMap="+parameterMap);

 returnparameterMap;

}

TreeNodeBase的构造方法有三种:

TreeNodeBase()

TreeNodeBase(java.lang.Stringtype,java.lang.Stringdescription,booleanleaf)

TreeNodeBase(java.lang.Stringtype,java.lang.Stringdescription,java.lang.Stringidentifier,booleanleaf)

最后一个参数表示是否是未级节点。

把XHTML中的代码与bean中的方法和构造方法联系起来看就比较容易了。

第一个参数是type,也就是

facetname="root">对应的如何渲染的部分;第二个参数是description,也就是tree要显示的内容;第三个参数是treeNode的ID;第四个参数表示是否有下级节点

 

1.前言

在JSF的项目开发中,用到树形菜单时可以考虑使用myfacs实现的tree2组件。

网上已经有很多文章对tree2进行介绍,我这里主要对一些重点进行描述,提醒使用者一些注意事项。

2.Tree2的组件

您可以到http:

//myfaces.apache.org/tomahawk下载tomahawk包,放到项目的lib路径中.

我这里使用的是tomahawk-1.1.5.jar.

然后再页面头部加上下面一行:

<%@tagliburi="http:

//myfaces.apache.org/tomahawk"prefix="t"%>

3.编写JS

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1