使用Angularjs在动态列表项中添加事件stopPropagation

时间:2018-06-06 14:24:56

标签: javascript jquery angularjs

如何在单击展开/折叠图标时停止隐藏树视图?但是单击树视图中的名称/项应隐藏树视图。下面是一个示例实现,其中下拉列表将使用searchbox显示/隐藏树视图。当我单击搜索框时,单击展开/折叠图标时,树视图组件应保持显示相同的状态。但是当我点击树视图时它应该隐藏。当我将鼠标悬停在树视图组件之外时,它应该隐藏。列表项是在组件内动态创建的。我尝试在列表项元素的click事件中传递事件,然后调用了event.stopPropagation,但它不起作用。有什么想法吗?

dropdowntreeview.html

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>Demo angular-tree-dropdown</title>
    <link rel='stylesheet' href="dropdowntreeview.css" />
    <link rel='stylesheet' href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" />
    <link rel='stylesheet' href="dropdowntreeview.css" />
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js" ></script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js" ></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js" ></script>


    <script src="dropdowntreeview.js"></script>
</head>
<body>

<div ng-app="myApp">
  <div ng-controller="myController" class="dropdown dropdown-scroll">

    <div class="btn btn-default dropdown-toggle" id="dropdownMenu1" data-toggle="dropdown" style="margin:10px 0 30px 0; padding:10px; background-color:#EEEEEE; border-radius:5px; font:12px Tahoma;">
      <span><b>Selected Node</b> : {{mytree.currentNode.roleName}}</span>
    </div>
    <div class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu1">
      <input ng-model='treeSearchQuery' type="text" placeholder="Search in tree..."/>
    <div
      data-angular-treeview="true"
      data-tree-id="mytree"
      data-tree-model="roleList"
      data-node-id="roleId"
      data-node-label="roleName"
      data-node-children="children"
      data-search-query='treeSearchQuery'>
    </div>
    </div>

  </div>
</div>
<body>
</html>

dropdowntreeview.js

(function(){

  //angular module
  var myApp = angular.module('myApp', ['angularTreeview']);

  //test controller
  myApp.controller('myController', function($scope){

    //test tree model 2
    $scope.roleList2 = [
        { "roleName" : "User default expanded", "roleId" : "role1", "expanded" : true, "children" : [
          { "roleName" : "subUser1 non-openable folder", "roleId" : "role11" },
          { "roleName" : "subUser2", "roleId" : "role12", "expanded" : true, "children" : [
              { "roleName" : "subUser2-1", "roleId" : "role121", "expanded" : true, "children" : [
              { "roleName" : "subUser2-1-1 folder ico", "roleId" : "role1211" },
                  { "roleName" : "subUser2-1-2 file ico", "roleId" : "role1212" , "fileicon" : true}
            ]}
          ]}
        ]},

        { "roleName" : "Admin default collapsed", "roleId" : "role2", "children" : [
          { "roleName" : "subAdmin1", "roleId" : "role11",  "children" : [] },
          { "roleName" : "subAdmin2", "roleId" : "role12", "children" : [
            { "roleName" : "subAdmin2-1", "roleId" : "role121", "children" : [
              { "roleName" : "subAdmin2-1-1", "roleId" : "role1211", "children" : [] },
              { "roleName" : "subAdmin2-1-2", "roleId" : "role1212", "children" : [] }
            ]}
          ]}
        ]}
      ];



    //roleList1 to treeview
    $scope.roleList = $scope.roleList2;

$('.dropdown-menu').find('input').click(function (e) {
    e.stopPropagation();
});


  });

})();

(function(angular) {
 'use strict';
 angular.module('angularTreeview', []).directive('treeModel', ['$compile', function($compile) {
  return {
   restrict: 'A',
   link: function(scope, element, attrs) {
    var treeId = attrs.treeId;
    var treeModel = attrs.treeModel;
    var nodeId = attrs.nodeId;
    var nodeLabel = attrs.nodeLabel;
    var nodeChildren = attrs.nodeChildren;
    var searchQuery = attrs.searchQuery;

    var template = '<ul>' + '<li data-ng-repeat="node in ' + treeModel + 
        ' | filter:' + searchQuery + ' ">' +
        '<i class="collapsed" data-ng-class="{nopointer: !node.' +
        nodeChildren + '.length}"' + 
        'data-ng-show="!node.expanded && !node.fileicon" data-ng-click="' +
        treeId + '.selectNodeHead(node,event)"></i>' + 
        '<i class="expanded" data-ng-show="node.expanded && !node.fileicon" data-ng-click="' +
        treeId + '.selectNodeHead(node)"></i>' +
        '<i class="normal" data-ng-show="node.fileicon"></i> ' +
        '<span title="{{node.' + nodeLabel + '}}" data-ng-class="node.selected" data-ng-click="' + 
        treeId + '.selectNodeLabel(node)">{{node.' + nodeLabel + '}}</span>' +
        '<div data-ng-show="node.expanded" data-tree-id="' +
        treeId + '" data-tree-model="node.' + nodeChildren + 
        '" data-node-id=' + nodeId + ' data-node-label=' + nodeLabel + 
        ' data-node-children=' + nodeChildren + ' data-search-query=' +
         searchQuery + '></div>' + '</li>' + '</ul>';
    if (treeId && treeModel) {
     if (attrs.angularTreeview) {
      scope[treeId] = scope[treeId] || {};
      scope[treeId].selectNodeHead = scope[treeId].selectNodeHead || function(selectedNode,event) {
          //below code is not working! 
          event.stopPropagation();
       if (selectedNode[nodeChildren] !== undefined) {
        selectedNode.expanded = !selectedNode.expanded;
       }
      };
      scope[treeId].selectNodeLabel = scope[treeId].selectNodeLabel || function(selectedNode) {
       if (scope[treeId].currentNode && scope[treeId].currentNode.selected) {
        scope[treeId].currentNode.selected = undefined;
       }
       selectedNode.selected = 'selected';
       scope[treeId].currentNode = selectedNode;
      };
     }
     element.html('').append($compile(template)(scope));
    }
   }
  };
 }]);
})(angular);

dropdowntreeview.css

div[data-angular-treeview] {
  /* prevent user selection */
  -moz-user-select: -moz-none;
  -khtml-user-select: none;
  -webkit-user-select: none;
  -ms-user-select: none;
  user-select: none;

  /* default */
  font-family: Tahoma;
  font-size:13px;
  color: #555;
  text-decoration: none;
}

div[data-tree-model] ul {
  margin: 0;
  padding: 0;
  list-style: none; 
  border: none;
  overflow: hidden;
}

div[data-tree-model] li {
  position: relative;
  padding: 0 0 0 20px;
  line-height: 20px;
}

div[data-tree-model] li .expanded {
  padding: 1px 10px;
  background-image: url("collapse-icon.png");
  background-repeat: no-repeat;
}

div[data-tree-model] li .collapsed {
  padding: 1px 10px;
  background-image: url("expand-icon.png");
  background-repeat: no-repeat;
}

div[data-tree-model] li .normal {
  padding: 1px 10px;
  background-image: url("");
  background-repeat: no-repeat;
}

div[data-tree-model] li i, div[data-tree-model] li span {
  cursor: pointer;
}

div[data-tree-model] li .selected {
  background-color: #aaddff;
  font-weight: bold;
  padding: 1px 5px;
}

.dropdown.dropdown-scroll .dropdown-menu {
    max-height: 200px;
    width: 60px;
    overflow: auto;
}

1 个答案:

答案 0 :(得分:1)

调用selectNodeHead函数时,必须添加$event作为输入参数。

从您的代码(重构,仅用于人类可读性,backtick approach

var template = `
    <ul>
        <li data-ng-repeat="node in ${treeModel} | filter: ${searchQuery}">
            <i 
                class="collapsed" 
                data-ng-class="{nopointer: !node.${nodeChildren}.length}" 
                data-ng-show="!node.expanded && !node.fileicon" 
                data-ng-click="${treeId}.selectNodeHead(node, $event)"
            ></i>
            <i 
                class="expanded" 
                data-ng-show="node.expanded && !node.fileicon" 
                data-ng-click="${treeId}.selectNodeHead(node, $event)"
            ></i>
            <i 
                class="normal" 
                data-ng-show="node.fileicon"
            ></i>
            <span 
                title="{{ node.${nodeLabel} }}" 
                data-ng-class="node.selected" 
                data-ng-click="${treeId}.selectNodeLabel(node)"
            >{{ node.${nodeLabel} }}</span>
            <div 
                data-ng-show="node.expanded" 
                data-tree-id="${treeId}" 
                data-tree-model="node.${nodeChildren}" 
                data-node-id="${nodeId}" 
                data-node-label="${nodeLabel}" 
                data-node-children="${nodeChildren}" 
                data-search-query="${searchQuery}"
            ></div>
        </li>
    </ul>
`;

希望它有所帮助。