zoukankan      html  css  js  c++  java
  • kendoUi_treeview

    前两天用kendoUI的treeView做了一个给用户角色分配菜单权限的功能,废了老大的劲,写来说明一下,

    做出效果如图:

    业务流程:点击”分配菜单权限“按钮,弹出一个新的window,并显示出所有的菜单选项,菜单分子父两级,因为这里是修改权限,

    显示时,根据行选的用户已有权限需要默认打钩,点击“提交查询”按钮,form提交,根据勾选情况,入库。

    下面说说一下实现代码:

     1,首先,自定义分配菜单权限按钮,grid 右边一栏为command,

    command : [ 
                            {
                                
                                text : "分配菜单权限",
                                
                                click: function(e) {
                                    // e.target is the DOM element representing the button
                                    var tr = $(e.target).closest("tr"); // get the current table row (tr)
                                    // get the data bound to the current table row
                                    var data = this.dataItem(tr);
                                    showTree(data.id).data("kendoWindow").open();
    }
    }, { name :
    "edit", text : { edit : "信息修改", cancel : "关闭", update : "提交" } }, { name : "destroy", text : "删除" } ],

     解释:通过var tr = $(e.target).closest("tr"); var data = this.dataItem(tr); 获得的data对应每一行的一跳数据,格式是json,几对应后台的JavaBean

    并将没一行的主键可获取 以作为标示,这里data.id  即为点击对应那一行的role的id

     2,弹出窗口,展示菜单menu树形结构: showTree(data.id).data("kendoWindow").open();

    showTree是一个方法 如下:
    function showTree(roleId){
            return $("#menuTree").kendoWindow({
                 "300px",
                height : "300px",
                position: {
                    top: 100,
                    left: 500
                  },
                title: "分配菜单权限",
                visible: false,
                content: 'role/menuTreePage.do?roleId='+roleId,
                activate : function(){
    
                },
                close : function(){
                    console.log("清除树");
                    $("#treeview").data("kendoTreeView").destroy();
                }
            });
        }
    menuTree 为在此grid 的jsp中定义的一个占位div

    <div id="menuTree"></div>
    即通过这个div生成一个弹窗kendoWindow,而这个弹窗中的内容实际上显示的是另外一个jsp页面rolemenu.jsp,content: 'role/menuTreePage.do?roleId='+roleId,
    通过这个属性的配置将另一个jsp中的内容包裹到kendoWindow中,rolemenu.jsp中真正的菜单menu的树形结构
    3,树形结构的配置
    <body>
    <div id="treeview" class="demo-section"></div>
    <form id="treeForm" action="<spring:url value='/role/assignMenus.do' />" method="post" onsubmit="return  false;">
        <input type="hidden" name="menuIds" id="result" /> 
        <input type="hidden" name="roleId" id="roleId" value="${roleId}"/> 
        <input id="formSub" type="submit" />
    </form>
    <script type="text/javascript">
    $(function() {
        var homogeneous = new kendo.data.HierarchicalDataSource({
            transport : {
                read : {
                    url : "role/menuTree.do",
                    dataType : "json",
                    data: function() {
                        var uproleId= $("#roleId").val();
                        return {roleId:uproleId}
                      }
                }
            },
            schema : {
                model : {
                    id : "id",
                    hasChildren : "hasChildren",
                    children:"items",
                    expanded : true,
                    checked : "checked"
                },
            }
        });
        
        $("#treeview").kendoTreeView({
            //loadOnDemand : false,// 延迟加载,默认是true,这里设置false是因为在初始化闭合的时候,如果选中根元素,是不法获取子节点id的
            dataSource : homogeneous,
            dataTextField : "name",
            checkboxes : {
                checkChildren : true
            }
        });
    
    
        var options = {
            success : function(data) {
                console.log(data);
                //location.href = "http://localhost:8085/csop_monitor/index.do";
                $("#menuTree").data("kendoWindow").close();
            }
        };
    
        $("#formSub").click(function() {
            var result = $("#result").val();
            var oldRs = $("#oldResult").val();
            if(result == ""){
                $("#menuTree").data("kendoWindow").close();
                return false;
            }else{
                    $("#result").val(result);        
            }
            //alert("re="+result);
            $("#treeForm").ajaxSubmit(options);
    
        });
        
    
    
    // show checked node IDs on datasource change
    $("#treeview").data("kendoTreeView").dataSource.bind("change",    getChangeValue);
    
    function getChangeValue(){
    
        var checkedNodes = [],
        treeView = $("#treeview").data("kendoTreeView"),
        message;
        checkedNodeIds(treeView.dataSource.view(), checkedNodes);
    
    
        if (checkedNodes.length > 0)
            message = checkedNodes.join(",");
        $("#result").val(message);
        console.log("改变后result : " + $("#result").val());
    }
    
    //function that gathers IDs of checked nodes
    function checkedNodeIds(nodes, checkedNodes) {
        for (var i = 0; i < nodes.length; i++) {
            if (nodes[i].checked) {
                console.log("checked node : " + nodes[i].id);
                checkedNodes.push(nodes[i].id);
            }
    
            if (nodes[i].hasChildren) {
                checkedNodeIds(nodes[i].children.view(), checkedNodes);
            }
    
        }
    }
    
    
    
    
    });
    </script>
    </body>
    
    

    treeView的完成,首先定义个个datasource,我这里定义了一个 HierarchicalDataSource,这个本身就是一个树形结构的datasouce

    值得注意的是schema的配置

    schema : {
                model : {
                    id : "id",
                    hasChildren : "hasChildren",
                    children:"items",
                    expanded : true,
                    checked : "checked"
                },
            }

    hasChildren,children,checked 都对应后台传递过来的javabean中的属性

    checked,hasChildren 为Boolean类型

    children 如果有,会自动生成一个树形,但是这个有一个问题就是JavaBean中必须定义为items,否则treeview找不到,我不知道是不是treeview那边还需要配置一个属性。

    checked 由于我的树形前有checkbox,如果未true,kendo也会自动选中,

    然后就简单了 ,同样通过一个div来显示treeview

    <div id="treeview" class="demo-section"></div>
     $("#treeview").kendoTreeView...
    这样就可以显示了,后台对menus的操作等下再说
    我这里还定义了一个form,用于提交,用户进行选择,操作之后的数据保存,通过tree的change事件保存下所选的menuIds,即可,
    通过这个方法 getChangeValue,这里不再赘述。
    最后:后台获取menus
    思路:首先抓取所有的menus,再通过roleID查询这个角色所拥有的menu权限找到对应的menu,将checked 设为true
    @RequestMapping("/menuTree.do")
    	@ResponseBody
    	public List<SysMenuDto>  menuListTree(@RequestParam(value = "roleId", required = false) String roleId) {
    		List<SysMenuDto> menuDtos = roleService.getRoleMenuTreeForUpdate(roleId);
    		return menuDtos;
    	}
    
    
    
    @Override
    	public List<SysMenuDto> getRoleMenuTreeForUpdate(String roleId) {
    		Role role=roleDao.get(roleId, Role.class);
    		List<SysMenu> roleRoleMenus = new ArrayList<SysMenu>();
    		Iterator<RoleMenuMap> it = role.getRoleMenuMaps().iterator();
    		while (it.hasNext()) {
    			RoleMenuMap roleMenuMap = it.next();
    			roleRoleMenus.add(roleMenuMap.getMenu());
    		}
    		List<SysMenu> menus=menuDao.listRootMenus();
    		List<SysMenuDto> menuDtos=new ArrayList<>();
    		for (SysMenu SysMenu : menus) {
    			SysMenuDto menuDto=new SysMenuDto().convertToDto(SysMenu);
    			
    			if(roleRoleMenus.contains(SysMenu)){
    				menuDto.setChecked(true);
    			}else{
    				menuDto.setChecked(false);
    			}
    			List<SysMenu> chiledMenus=SysMenu.getChildren();
    			if(chiledMenus!=null&&chiledMenus.size()>0){
    				for(int i=0;i<chiledMenus.size();i++){
    					SysMenu childMenu=chiledMenus.get(i);
    					if(roleRoleMenus.contains(childMenu)){
    						menuDto.getItems().get(i).setChecked(true);
    					}else{
    						menuDto.getItems().get(i).setChecked(false);
    					}
    				}
    				
    			}
    			menuDtos.add(menuDto);
    		}
    		return menuDtos;
    	}
    

     menuDto

    	private String name;
    
    	private String url;
    
    	private String desc;
    
    	private int order;
    
    	private String createdTime;
    
    	private String parentId;
    	
    	private String parentName;
    
    	private List<SysMenuDto> items = new ArrayList<>();
    	
    	private boolean hasChildren;
    	
    	private boolean checked;
    
    	@Override
    	public SysMenuDto convert(SysMenu o) {
    		this.setId(o.getId());
    		this.setCreatedTime(DateUtils.date2String(o.getCreatedTime()));
    		this.setDesc(o.getDesc());
    		this.setName(o.getName());
    		this.setUrl(o.getUrl());
    		this.setOrder(o.getOrder());
    		this.setParentId(o.getParent() == null ? null : o.getParent().getId());
    		this.setParentName(o.getParent() == null ? "无" : o.getParent().getName());
    		List<SysMenu> sysMenus = o.getChildren();
    		for (SysMenu sysMenu : sysMenus) {
    			items.add(new SysMenuDto().convert(sysMenu));
    		}
    		this.hasChildren = sysMenus != null && sysMenus.size() > 0 ? true : false;
    		return this;
    	}
    	
    	
    	public SysMenu convertToEntity(SysMenu menu) {
    		//menu.setId(this.getId());
    		menu.setDesc(this.desc);
    		menu.setName(this.name);
    		menu.setUrl(this.url);
    		menu.setOrder(this.order);
    		//menu.setParent(parent);
    		//menu.setChildren(children);
    
    		return menu;
    	}
    
    
    //getter and setter .....
    

    附:两个完整jsp代码

    role.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>  
    <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>  
    <%@ taglib prefix='spring' uri="http://www.springframework.org/tags" %>
    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
    
    <head>
    <script src="<spring:url value='/resources/js/plugins/jquery.form.js' />"></script>
    <script type="text/javascript">
    
    $(function() {
        
        var prefix = "role";
        
        var dataSource = new kendo.data.DataSource({
            type: "odata",
            pageSize : 20,
            serverPaging: true,//服务器端是否进行分页查询
            serverFiltering: true,
            transport : {
                read : {
                    url : prefix + '/showRoles.do',
                    dataType : "json",
                },
                update: {
                    url: prefix + '/save.do',
                    dataType: "json", 
                    contentType:"application/x-www-form-urlencoded",
                    type : "post",
                },
                destroy: {
                  url: prefix + '/delete.do',
                  contentType:"application/x-www-form-urlencoded",
                  type : "post",
                },
                create: {
                    url: prefix + '/save.do',
                    dataType: "json",
                    contentType:"application/x-www-form-urlencoded",
                    type : "post",
                },
                parameterMap: function(data, type) {
                    if (type !== "read" && data) {
                       // return kendo.stringify(data);
                    }
                    return data;
                }
            },
            schema : {
                model : {
                    id : "id",
                    fields : {
                        id : {type : "string"},
                        name : {type : "string"},
                        status : {
                            type : "string",
                            defaultValue:"激活"
                            },
                        desc : {type : "string"},
                    }
                }
            },
            //after create update destory. reload the datasource(reflesh page)
            requestEnd: function(e) {
                var response = e.response;
                var type = e.type;
                if(type != "read"){
            
                    this.read();
                }
            }
        });
        $("#grid").kendoGrid({
                dataSource : dataSource,
                sortable : false,
                selectable : "multiple",// 多选
                height : 500,
                navigatable: true,
                 editable: true,
                toolbar : [ 
                    {
                        name : "create",
                        text : "新增角色"
                    }
                ],
                pageable : {
                    pageSize : 20,// 一页显示多少行数据
                    previousNext : true,// 是否允许有上一页、下一页、首页、尾页摁扭
                    numeric : true,// 是否显示翻页处的页数按钮
                    buttonCount : 5,// 限制页数按钮的显示个数
                    input : false,// 是否显示输入页数的文本框
                    refresh : true,// 是否允许刷新页面
                    pageSizes : true,// 是否允许调整一页显示的行数,可设置[5, 10, 15]
                    messages : {
                        display : "显示  {0}-{1} 条数据 总共 {2} 条数据",
                        empty : "没有数据",
                        itemsPerPage : "选择显示行数",
                        refresh : "刷新",
                        previous : "上一页",
                        next : "下一页",
                        last : "尾页",
                        first : "首页"
                    }
                },
                columns : [ // 显示列定义
                    {
                        field : "name",
                        width : 100,
                        title : "角色名"
                    }, {
                        field : "desc",
                        width : 120,
                        title : "描述"
                    }, {
                        field : "status",
                        width : 80,
                        title : "启动状态",
                        editor : activeDownEditor,
                        template : "#=status#"
                    }, {
                        command : [ 
                            {
                                
                                text : "分配菜单权限",
                                
                                click: function(e) {
                                    // e.target is the DOM element representing the button
                                    var tr = $(e.target).closest("tr"); // get the current table row (tr)
                                    // get the data bound to the current table row
                                    var data = this.dataItem(tr);
                                    var menuIds = [];
                                    console.log(data);
                                    if(data.roleMenuMapDtos != null)
                                        for(var i = 0; i < data.roleMenuMapDtos.length; i++){
                                            menuIds.push(data.roleMenuMapDtos[i].menu.id);
                                        }
                                    showTree(data.id, menuIds).data("kendoWindow").open();
                                  }
                            }, {
                                name : "edit",
                                text : {
                                    edit : "信息修改",
                                    cancel : "关闭",
                                    update : "提交"
                                }
                            }, {
                                name : "destroy",
                                text : "删除"
                            } 
                        ],
                        title : "操作",
                        width : "160px"
                    } ],
                    editable : {// 设置可以在列表中进行编辑数据
                        // 设置删除时显示的确认信息
                        confirmation : "您确定要进行删除操作吗?",
                        destroy : true,// 不允许删除
                        mode : "popup",// 设置编辑形式为弹出框(popup)还是在列表中(inline)
                        //template: kendo.template($("#editTemplate").html())//设置弹出框中加载的内容,设置此项mode必须是popup
                    },
                    groupable : false
            });
        
        var data = [
                    { text: "激活", value: "激活" },
                    { text: "冻结", value: "冻结" }
                ];
        
        function activeDownEditor(container, options){
    //        console.log(options);
            var status = options.model.status;
            var rolestatusDroplist=$('<input required  data-text-field="text" data-value-field="value" data-bind="value:' + options.field + '"/>')
            .appendTo(container).kendoDropDownList({
                dataTextField: "text",
                dataValueField: "value",
                dataSource : data
            });
            rolestatusDroplist.data("kendoDropDownList").select(function(dataItem) {
                return dataItem.text === status;
            });
        }
        function showTree(roleId, menuIds){
            return $("#menuTree").kendoWindow({
                 "300px",
                height : "300px",
                position: {
                    top: 100,
                    left: 500
                  },
                title: "分配菜单权限",
                visible: false,
                content: 'role/menuTreePage.do?roleId='+roleId,
                activate : function(){
                     $("#roleId").val(roleId);
                    //var treeview = $("#treeview").data("kendoTreeView");
                    //console.log("role.reosurce : " + menuIds);
                    //var nodes = treeview.dataSource.view();
                    //if(menuIds.length > 0)
                    //checkedNodes(nodes, menuIds);
                    //treeview.updateIndeterminate();
                    
                    //if (checkedNodes.length > 0) 
                     //   message = menuIds.join(",");
                  //  $("#oldResult").val(message);
                   
                  //  console.log("roleId : " + $("#roleId").val() + "    oldresult : " + $("#oldResult").val());
                },
                close : function(){
                    console.log("清除树");
                    $("#treeview").data("kendoTreeView").destroy();
                }
            });
        }
        
        function checkedNodes(nodes, checkedNodesID) {
            //console.log("nodes=---"+nodes);
            for (var i = 0; i < checkedNodesID.length; i++) {
                for(var j = 0; j < nodes.length; j++){
                //console.log("node id : " + nodes[j].id + "   checked Id : " + checkedNodesID[i]);
                    if(nodes[j].id == checkedNodesID[i]){
                        nodes[j].checked = true;
                        console.log("node.id : " + nodes[j].id + "    node.name : " + nodes[j].name + " is checked : " + nodes[j].checked);
    //                    console.log(nodes[j].name + "   " + nodes[j].hasChildren);
                        if(nodes[j].hasChildren)
                            checkedNodes(nodes[j].children.view(),checkedNodesID);
                    }else{
                        nodes[j].checked = false;
                        }
                }
            }
        }
        /*
        function chilrenChecked(children){
            for(var i = 0; i < children.length; i++){
                children[i].checked = true;
                console.log("children name : " + children[i].name + "    checked : " + children[i].checked);
            }
        }*/
    
        //for rolemenu
    
    
    
    
    
        
        
    });
    
    </script>
    </head>
    <body>
    <div id="menuTree"></div>
    <div id="example" class="k-content">
            <div id="clientsDb">
                <div id="grid" style="height: 380px"></div>
            </div>
    </div>
    <div id="dialog"></div>
    </body>

    rolemenu.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>  
    <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>  
    <%@ taglib prefix='spring' uri="http://www.springframework.org/tags" %>
    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
    
    <head>
    <script src="<spring:url value='/resources/js/plugins/jquery.form.js' />"></script>
    
    </head>
    <body>
    <div id="treeview" class="demo-section"></div>
    <form id="treeForm" action="<spring:url value='/role/assignMenus.do' />" method="post" onsubmit="return  false;">
        <input type="hidden" name="menuIds" id="result" /> 
        <input type="hidden" name="roleId" id="roleId" value="${roleId}"/> 
        <input id="formSub" type="submit" />
    </form>
    <script type="text/javascript">
    $(function() {
        var homogeneous = new kendo.data.HierarchicalDataSource({
            transport : {
                read : {
                    url : "role/menuTree.do",
                    dataType : "json",
                    data: function() {
                        var uproleId= $("#roleId").val();
                        return {roleId:uproleId}
                      }
                }
            },
            schema : {
                model : {
                    id : "id",
                    hasChildren : "hasChildren",
                    children:"items",
                    expanded : true,
                    checked : "checked"
                },
            }
        });
        
        $("#treeview").kendoTreeView({
            //loadOnDemand : false,// 延迟加载,默认是true,这里设置false是因为在初始化闭合的时候,如果选中根元素,是不法获取子节点id的
            dataSource : homogeneous,
            dataTextField : "name",
            checkboxes : {
                checkChildren : true
            }
        });
    
    
        var options = {
            success : function(data) {
                console.log(data);
                //location.href = "http://localhost:8085/csop_monitor/index.do";
                $("#menuTree").data("kendoWindow").close();
            }
        };
    
        $("#formSub").click(function() {
            var result = $("#result").val();
            var oldRs = $("#oldResult").val();
            if(result == ""){
                $("#menuTree").data("kendoWindow").close();
                return false;
            }else{
                    $("#result").val(result);        
            }
            //alert("re="+result);
            $("#treeForm").ajaxSubmit(options);
    
        });
        
    
    
    // show checked node IDs on datasource change
    $("#treeview").data("kendoTreeView").dataSource.bind("change",    getChangeValue);
    
    function getChangeValue(){
        //console.log("改变前result : " + $("#oldResult").val());
        var checkedNodes = [],
        treeView = $("#treeview").data("kendoTreeView"),
        message;
        
        //console.log("treeView : " + treeView.dataSource.view().length > 0);
        checkedNodeIds(treeView.dataSource.view(), checkedNodes);
        //console.log(checkedNodes);
    
        if (checkedNodes.length > 0)
            message = checkedNodes.join(",");
    
        //alert("message="+message);
    
        $("#result").val(message);
        console.log("改变后result : " + $("#result").val());
    }
    
    //function that gathers IDs of checked nodes
    function checkedNodeIds(nodes, checkedNodes) {
        for (var i = 0; i < nodes.length; i++) {
    //        console.log(nodes[i]);
    //        console.log(nodes[i].checked);
            if (nodes[i].checked) {
                console.log("checked node : " + nodes[i].id);
                checkedNodes.push(nodes[i].id);
            }
    
            if (nodes[i].hasChildren) {
                checkedNodeIds(nodes[i].children.view(), checkedNodes);
            }
            // console.log("node.id : " + nodes[i].id + " node.name : " +
            // nodes[i].name);
        }
    }
    
    
    
    
    });
    </script>
    </body>
  • 相关阅读:

    java 线程池
    java 普通内部类和静态内部类
    JVM
    java httpUtil
    maven 常见问题
    计算java对象的内存占用
    HTML5简单入门系列(九)
    HTML5简单入门系列(八)
    HTML5简单入门系列(七)
  • 原文地址:https://www.cnblogs.com/china2k/p/3795613.html
Copyright © 2011-2022 走看看