Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angularjs 是否可以创建具有角度的树状视图?_Angularjs - Fatal编程技术网

Angularjs 是否可以创建具有角度的树状视图?

Angularjs 是否可以创建具有角度的树状视图?,angularjs,Angularjs,我希望在web应用程序中以树状结构显示数据。我希望用Angular完成这项任务 看起来ng repeat允许我遍历节点列表,但是当给定节点的深度增加时,我如何进行嵌套呢 我尝试了,但是HTML的自动转义阻止了它的工作。另外,末端ul标签位于错误的位置 我敢肯定,我处理这个问题的方式是完全错误的 有什么想法吗?看看这把小提琴 原件: 更新: 这将使您很好地了解如何使用angular显示树状结构。这有点像在html中使用递归 这一个似乎更完整一些:另一个基于的示例,已经有一个示例树结构(在IMO中更

我希望在web应用程序中以树状结构显示数据。我希望用Angular完成这项任务

看起来ng repeat允许我遍历节点列表,但是当给定节点的深度增加时,我如何进行嵌套呢

我尝试了,但是HTML的自动转义阻止了它的工作。另外,末端ul标签位于错误的位置

我敢肯定,我处理这个问题的方式是完全错误的


有什么想法吗?

看看这把小提琴

原件:

更新:


这将使您很好地了解如何使用angular显示树状结构。这有点像在html中使用递归

这一个似乎更完整一些:

另一个基于的示例,已经有一个示例树结构(在IMO中更容易看到它是如何工作的)和一个用于搜索树的过滤器:


以下是使用递归指令的示例: 取自

module.directive(“树”,函数($compile){
返回{
限制:“E”,
作用域:{family:'='},
模板:
“{{family.name}

”+ “
    ”+ “
  • ”+ '' + “
  • ”+ “
”, 编译:函数(远程通讯,tAttr){ var contents=tElement.contents().remove(); var编译内容; 返回函数(范围、IELENT、iAttr){ 如果(!compiledContents){ compiledContents=$compile(目录); } compiledContents(范围,函数(克隆,范围){ 附加(克隆); }); }; } }; });
如果您正在使用引导CSS

我已经基于引导“nav”列表为AngularJS创建了一个简单的可重用树控件(指令)。我添加了额外的缩进、图标和动画。HTML属性用于配置

它不使用递归

我叫它角引导导航树(你不觉得这个名字很吸引人吗?)


这里有一个例子,源代码是。

当做类似的事情时,最好的解决方案是递归指令。然而,当你发出这样的指令时,你会发现AngularJS陷入了一个无休止的循环

解决方案是让指令在编译事件期间删除元素,然后手动编译并将它们添加到链接事件中

我在中发现了这一点,并对这一功能进行了抽象

使用此服务,您可以轻松地生成树指令(或其他递归指令)。下面是树指令的一个示例:

module.directive("tree", function(RecursionHelper) {
    return {
        restrict: "E",
        scope: {family: '='},
        template: 
            '<p>{{ family.name }}</p>'+
            '<ul>' + 
                '<li ng-repeat="child in family.children">' + 
                    '<tree family="child"></tree>' +
                '</li>' +
            '</ul>',
        compile: function(element) {
            return RecursionHelper.compile(element);
        }
    };
});
module.directive(“树”,函数(RecursionHelper){
返回{
限制:“E”,
作用域:{family:'='},
模板:
“{{family.name}

”+ “
    ”+ “
  • ”+ '' + “
  • ”+ “
”, 编译:函数(元素){ 返回RecursionHelper.compile(元素); } }; });
看这个演示。 我最喜欢这个解决方案,因为:

  • 你不需要一个特殊的指令,使你的html不那么干净
  • 递归逻辑被抽象到RecursionHelper服务中,因此您可以保持指令干净

  • 更新:增加了对自定义链接功能的支持。

    对我来说似乎做得很好

    这么多伟大的解决方案,但我觉得它们都以某种方式使事情变得有点复杂

    我想创建一些东西,重新创建@Mark Lagendijk的awnser的简单性,但是没有在指令中定义模板,而是让“用户”用HTML创建模板

    从……中汲取思想。。。我最终创建了这个项目:

    它允许您构建树,如:

    <ul dx-start-with="rootNode">
      <li ng-repeat="node in $dxPrior.nodes">
        {{ node.name }}
        <ul dx-connect="node"/>
      </li>
    </ul>
    
    • {{node.name}
    对我来说,这比为不同结构的树创建多个指令更干净。。。。从本质上讲,将上述内容称为树有点错误,它从@ganaraj的awnser的“递归模板”中提取了更多信息,但允许我们在需要树的地方定义模板

    (您可以使用基于脚本标记的模板来实现这一点,但它仍然必须位于实际的树节点之外,而且它仍然感觉有点不舒服……)

    留下来只是另一个选择…

    您可以尝试使用带有角度Ui树的示例,但我已编辑,与表、网格和列表的兼容性

    • 可拖放
    • 列表的扩展函数指令(next、prev、getChildren等)
    • 过滤数据
    • 订购人(版本)

    • 是的,这绝对是可能的。这里的问题可能假设角度为1.x,但为了将来参考,我将包括一个角度为2的示例:

      从概念上讲,您只需创建一个递归模板:

      <ul>
          <li *for="#dir of directories">
      
              <span><input type="checkbox" [checked]="dir.checked" (click)="dir.check()"    /></span> 
              <span (click)="dir.toggle()">{{ dir.name }}</span>
      
              <div *if="dir.expanded">
                  <ul *for="#file of dir.files">
                      {{file}}
                  </ul>
                  <tree-view [directories]="dir.directories"></tree-view>
              </div>
          </li>
      </ul>
      
        {{dir.name}} {{file}}
    然后将树对象绑定到模板,并让Angular发挥其魔力。这个概念显然也适用于角度1.x


    下面是一个完整的示例:

    您可以使用角度递归注入器:

    允许您通过调节进行无限深度嵌套。仅在需要时进行重新编译,并且只编译正确的元素。代码没有魔力

    <div class="node">
      <span>{{name}}</span>
    
      <node--recursion recursion-if="subNode" ng-model="subNode"></node--recursion>
    </div>
    
    
    {{name}}
    

    与其他解决方案相比,它工作得更快、更简单的原因之一是“-recursion”后缀。

    当树结构较大时,角度(高达1.4.x)在呈现递归模板时变得非常缓慢。在尝试了这些建议之后
    <ul>
        <li *for="#dir of directories">
    
            <span><input type="checkbox" [checked]="dir.checked" (click)="dir.check()"    /></span> 
            <span (click)="dir.toggle()">{{ dir.name }}</span>
    
            <div *if="dir.expanded">
                <ul *for="#file of dir.files">
                    {{file}}
                </ul>
                <tree-view [directories]="dir.directories"></tree-view>
            </div>
        </li>
    </ul>
    
    <div class="node">
      <span>{{name}}</span>
    
      <node--recursion recursion-if="subNode" ng-model="subNode"></node--recursion>
    </div>
    
    function menu_tree(menu, prefix) {
        var html = '<div>' + prefix + menu.menu_name + ' - ' + menu.menu_desc + '</div>\n';
        if (!menu.items) return html;
        prefix += menu.menu_name + '/';
        for (var i=0; i<menu.items.length; ++i) {
            var item = menu.items[i];
            html += menu_tree(item, prefix);
        }
        return html;
    }
    // Generate the tree view and tell Angular to trust this HTML
    $scope.html_menu = $sce.trustAsHtml(menu_tree(menu, ''));
    
    <div ng-bind-html="html_menu"></div>
    
    menu = {menu_name: '', menu_desc: 'root', items: [
                {menu_name: 'bin', menu_desc: 'Essential command binaries', items: [
                    {menu_name: 'arch', menu_desc: 'print machine architecture'},
                    {menu_name: 'bash', menu_desc: 'GNU Bourne-Again SHell'},
                    {menu_name: 'cat', menu_desc: 'concatenate and print files'},
                    {menu_name: 'date', menu_desc: 'display or set date and time'},
                    {menu_name: '...', menu_desc: 'other files'}
                ]},
                {menu_name: 'boot', menu_desc: 'Static files of the boot loader'},
                {menu_name: 'dev', menu_desc: 'Device files'},
                {menu_name: 'etc', menu_desc: 'Host-specific system configuration'},
                {menu_name: 'lib', menu_desc: 'Essential shared libraries and kernel modules'},
                {menu_name: 'media', menu_desc: 'Mount point for removable media'},
                {menu_name: 'mnt', menu_desc: 'Mount point for mounting a filesystem temporarily'},
                {menu_name: 'opt', menu_desc: 'Add-on application software packages'},
                {menu_name: 'sbin', menu_desc: 'Essential system binaries'},
                {menu_name: 'srv', menu_desc: 'Data for services provided by this system'},
                {menu_name: 'tmp', menu_desc: 'Temporary files'},
                {menu_name: 'usr', menu_desc: 'Secondary hierarchy', items: [
                    {menu_name: 'bin', menu_desc: 'user utilities and applications'},
                    {menu_name: 'include', menu_desc: ''},
                    {menu_name: 'local', menu_desc: '', items: [
                        {menu_name: 'bin', menu_desc: 'local user binaries'},
                        {menu_name: 'games', menu_desc: 'local user games'}
                    ]},
                    {menu_name: 'sbin', menu_desc: ''},
                    {menu_name: 'share', menu_desc: ''},
                    {menu_name: '...', menu_desc: 'other files'}
                ]},
                {menu_name: 'var', menu_desc: 'Variable data'}
            ]
           }
    
    - root
    /bin - Essential command binaries
    /bin/arch - print machine architecture
    /bin/bash - GNU Bourne-Again SHell
    /bin/cat - concatenate and print files
    /bin/date - display or set date and time
    /bin/... - other files
    /boot - Static files of the boot loader
    /dev - Device files
    /etc - Host-specific system configuration
    /lib - Essential shared libraries and kernel modules
    /media - Mount point for removable media
    /mnt - Mount point for mounting a filesystem temporarily
    /opt - Add-on application software packages
    /sbin - Essential system binaries
    /srv - Data for services provided by this system
    /tmp - Temporary files
    /usr - Secondary hierarchy
    /usr/bin - user utilities and applications
    /usr/include -
    /usr/local -
    /usr/local/bin - local user binaries
    /usr/local/games - local user games
    /usr/sbin -
    /usr/share -
    /usr/... - other files
    /var - Variable data
    
    <div ng-app="Application" ng-controller="TreeController">
        <table>
            <thead>
                <tr>
                    <th>col 1</th>
                    <th>col 2</th>
                    <th>col 3</th>
                </tr>
            </thead>
            <tbody ng-repeat="item in tree">
                <tr>
                    <td>{{item.id}}</td>
                    <td>{{item.fname}}</td>
                    <td>{{item.lname}}</td>
                </tr>
                <tr ng-repeat="children in item.child">
                    <td style="padding-left:15px;">{{children.id}}</td>
                    <td>{{children.fname}}</td>
                </tr>
            </tbody>
         </table>
    </div>
    
    angular.module("myApp", []).
    controller("TreeController", ['$scope', function ($scope) {
        $scope.tree = [{
            id: 1,
            fname: "tree",
            child: [{
                id: 1,
                fname: "example"
            }],
            lname: "grid"
        }];
    
    
    }]);
    
    <script type="text/ng-template" id="tree_item_renderer.html">
        <div class="node"  ng-class="{selected: data.selected}" ng-click="select(data)">
            <span ng-click="data.hide=!data.hide" style="display:inline-block; width:10px;">
                <span ng-show="data.hide && data.nodes.length > 0" class="fa fa-caret-right">+</span>
                <span ng-show="!data.hide && data.nodes.length > 0" class="fa fa-caret-down">-</span>
            </span>
            <span ng-show="!data.editting" ng-dblclick="edit($event)" >{{data.name}}</span>
            <span ng-show="data.editting"><input ng-model="data.name" ng-blur="unedit()" ng-focus="f()"></input></span>
            <button ng-click="add(data)">Add node</button>
            <button ng-click="delete(data)" ng-show="data.parent">Delete node</button>
        </div>
        <ul ng-show="!data.hide" style="list-style-type: none; padding-left: 15px">
            <li ng-repeat="data in data.nodes">
                <recursive><sub-tree data="data"></sub-tree></recursive>
            </li>
        </ul>
    </script>
    <ul ng-app="Application" style="list-style-type: none; padding-left: 0">
        <tree data='{name: "Node", nodes: [],show:true}'></tree>
    </ul>
    
    angular.module("myApp",[]);
    
    /* https://stackoverflow.com/a/14657310/1309218 */
    angular.module("myApp").
    directive("recursive", function($compile) {
        return {
            restrict: "EACM",
            require: '^tree',
            priority: 100000,
    
            compile: function(tElement, tAttr) {
                var contents = tElement.contents().remove();
                var compiledContents;
                return function(scope, iElement, iAttr) {
                    if(!compiledContents) {
                        compiledContents = $compile(contents);
                    }
                    compiledContents(scope, 
                                         function(clone) {
                             iElement.append(clone);
                                             });
                };
            }
        };
    });
    
    angular.module("myApp").
    directive("subTree", function($timeout) {
        return {
            restrict: 'EA',
            require: '^tree',
            templateUrl: 'tree_item_renderer.html',
            scope: {
                data: '=',
            },
            link: function(scope, element, attrs, treeCtrl) {
                scope.select = function(){
                    treeCtrl.select(scope.data);
                };
                scope.delete = function() {
                    scope.data.parent.nodes.splice(scope.data.parent.nodes.indexOf(scope.data), 1);
                };
                scope.add = function() {
                    var post = scope.data.nodes.length + 1;
                    var newName = scope.data.name + '-' + post;
                    scope.data.nodes.push({name: newName,nodes: [],show:true, parent: scope.data});
                };
                scope.edit = function(event){
                    scope.data.editting = true;
                    $timeout(function(){event.target.parentNode.querySelector('input').focus();});
                };
                scope.unedit = function(){
                    scope.data.editting = false;
                };
    
            }
        };
    });
    
    
    angular.module("myApp").
    directive("tree", function(){
        return {
            restrict: 'EA',
            template: '<sub-tree data="data" root="data"></sub-tree>',
            controller: function($scope){
                this.select = function(data){
                    if($scope.selected){
                        $scope.selected.selected = false;
                    }
                    data.selected = true;
                    $scope.selected = data;
                };
            },
            scope: {
                data: '=',
            }
        }
    });