关于使用angular-tree-dnd遇到的坑

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhanglong_web/article/details/79507016

因为项目里要用到树形插件做个下拉的机构选择树形图,开始想到了angular-ui-tree,但是因为数据格式和我的数据格式不是很匹配,所以就弃用了,在github上找了另外一个,也就是今天的主角:angular-tree-dnd(https://github.com/thienhung1989/angular-tree-dnd)。
  先说说数据格式的问题,说到树形图,很多人脑子里出现的数据格式可能就是子节点套在父节点里面,子子节点再套在子节点里面,一层一层嵌套下去,这样的数据格式阅读起来结构是比较清晰,做成树形图的话依赖angular-ui-tree会比较好,下面是这种数据格式:

  {
    "id": 1,
    "title": "node1",
    "nodes": []
  }

  还有一种数据格式是通过parent_id来确定父子节点对应关系,而我现在的项目的数据格式就是这种:

[
  {
    "DemographicId": 1,
    "ParentId": null,
    "Name": "United States of America",
    "Description": "United States of America",
    "Area": 9826675,
    "Population": 318212000,
    "TimeZone": "UTC -5 to -10"
  },
  {
    "DemographicId": 2,
    "ParentId": 1,
    "Name": "California",
    "Description": "The Tech State",
    "Area": 423970,
    "Population": 38340000,
    "TimeZone": "Pacific Time"
  }
]

  就是通过DemographicId和ParentId来找到父子节点的对应关系,具体的angular-tree-dnd使用方法如下:
  1.安装依赖:
  bower install angular-tree-dnd
  2.依赖注入:
  angular.module('zyClient',['zyClient.directives','ntt.TreeDnD'])
  3.在你的控制器注入$TreeDnDConvert(用于转换id和parentId,下面会说到):
  ResourceControlCtrl = ['$scope','$TreeDnDConvert', ($scope, $TreeDnDConvert)
  4.页面的搭建:

tree-dnd(
  tree-class="dnd"
  tree-control="my_tree"
  tree-data="tree_data"
  column-defs="col_defs"
  indent="30"
  indent-plus="20"
  indent-unit="px"
)

5.控制器数据的处理:
  $scope.tree_data=$TreeDnDConvert.line2tree($scope.list, 'id', 'parent_id')
  这里也就是将父子节点的对应关系设置成id和parent_id,因为后端给你的数据不可能像是上述中的数据格式那样是DemographicId和ParentId,这个就是根据你的实际数据格式去转换了。
  接下来就要注意坑点了,github上给出的文档是节点是支持点击和选择事件的,分别是on-select和on-click

<tree-dnd
    tree-class="dnd"
    tree-data="tree_data"
    tree-control="my_tree"
    callbacks="callbacks"
    drag-enabled="true"
    icon-leaf="none"
    icon-expand="fa fa-fw fa-angle-right"
    icon-collapse="fa fa-fw fa-angle-down"
    template-url="tree-dnd-template.html"
    column-defs="col_defs"
    expand-on="expanding_property"
    on-select="my_tree_handler(node)"
    on-click="my_tree_handler(node)"
    data-indent="30"
    data-indent-unit="px"
    data-indent-plus="15"
>
</tree-dnd>

  而在我的实际使用中,大家也可以看到我的页面上并没有事件,原因是因为我加了事件并没有起到任何作用,也就是事件是失效的,这让我找了很久的文档,也没有发现有什么问题,开始以为是模板的问题,但是文档上很清楚的表示如果不传template-url也是有默认文档的,实在是找不出是什么原因导致事件失效,后来只好查看了源码:

$scope.onClick = function (node) {
   if (angular.isDefined($scope.tree) && angular.isFunction($scope.tree.on_click)) {
        // We want to detach from Angular's digest cycle so we can
        // independently measure the time for one cycle.
        setTimeout(
            function () {
                $scope.tree.on_click(node);
            }, 0
        );
    }
};

$scope.onSelect = function (node) {
    if (angular.isDefined($scope.tree)) {
        if (node !== $scope.tree.selected_node) {
            $scope.tree.select_node(node);
        }

        if (angular.isFunction($scope.tree.on_select)) {
            setTimeout(
                function () {
                    $scope.tree.on_select(node);
                }, 0
            );
        }
    }
};

  这是源码378行到404行的内容,我们可以很清楚看到事件是封装了的,但是我们再看看3348行默认的模板里TreeDnD.html是没有onClick的点击事件的,只有一个onSelect的事件,那我们在使用默认模板的时候当然也就没有办法使用onClick的事件。
这里写图片描述
既然onClick不行,那onSelect总该行吧,然而事实是绑在指令上的on-select=”select(node)”的事件也执行不了,这下就更懵了,结果看了一下onSelect事件的封装:

$scope.onSelect = function (node) {
    if (angular.isDefined($scope.tree)) {
        if (node !== $scope.tree.selected_node) {
            $scope.tree.select_node(node);
        }

        if (angular.isFunction($scope.tree.on_select)) {
            setTimeout(
                function () {
                    $scope.tree.on_select(node);
                }, 0
            );
        }
    }
};

  可以看到是必须是$scope.tree上绑定on_select,注意是on_select,格式要完全一样才可以调用,那我的控制器里的函数就是:

$scope.my_tree.on_select = (org) ->
  $scope.m.org = org
  $scope.showOrgone = false
  $scope.$apply()
  if m.role is 1
    _getSuperResourceStatic(org)
  else
    _getRoleResourceStatic(org)
  return

  到这一步事件才算能正常调用,其实挺坑的,没有使用之前如果知道这么坑也就不会再用了,github确实是个好地方,很多开源的框架的组件可以供我们使用,但是开源的坏处就是很多项目参差不齐,很可能不是很成熟就放出来供大家使用,这就会导致我们会遇到很多意想不到的坑,不过只要一点一点去看,大部分还是能找到问题所在的。
这里写图片描述

猜你喜欢

转载自blog.csdn.net/zhanglong_web/article/details/79507016