找到你要的答案

Q:How do you use a recursive function within a directive in angularJS?

Q:你怎么在AngularJS指令使用递归函数?

I'd like to create a ToDo app in AngularJS that uses nested ToDos. As part of this, I'd like the ability to indent or outdent a ToDo with a click (ultimately, it will react to a 'tab' or 'shift-tab' keypress). When indenting, the function should also indent any child ToDos. This is where I'm having trouble. I'm not sure how to implement a recursive function in a directive. If anyone has seen this done or could offer any help, i would appreciate it. I've created a working JSFiddle that indents a single ToDo but doesn't indent it's children. JS Fiddle is here https://jsfiddle.net/t1ba50k6/16/

Also, please offer any best practices on coding convention or to clean up the directive.

Thanks!

My HTML:

<ul id=Todos ng-app="app" ng-controller="todos">
    <div ng-repeat='todo in model' ng-init="todoIndex = $index">
       <todo-item content="todo"></todo-item>
    </div>

My javascript:

var app = angular.module('app', []);

app.controller("todos", function ($scope) {

    $scope.model = [{
        "title": "Task item one",
            "indentLevel": 1
    }, {
        "title": "Task item two",
            "indentLevel": 2
    }, {
        "title": "Task item three",
            "indentLevel": 2
    }];

});


app.directive('todoItem', function ($compile) {

    var getTemplate = function (content) {
        var startStr = '';
        var endStr = '';

        if (content.indentLevel == 1) {
            startStr = '<li class="todolist"><table><tr><td><div class="checkboxpadding"><img width="16" height="16" class="checkbox"></div></td><td><div ng-click="indent()">';
            endStr = '</div></td></tr></table></li>';

            return startStr + content.title + endStr;
        } else if (content.indentLevel == 2) {

            startStr = '<li class="todolist indent_2""><table><tr><td><div class="checkboxpadding"><img width="16" height="16" class="checkbox"></div></td><td><div ng-click="indent()">';
            endStr = '</div></td></tr></table></li>';
            return startStr + content.title + endStr;
        }


    };

    var linker = function (scope, element, attrs) {

        element.html(getTemplate(scope.content)).show();
        $compile(element.contents())(scope);


        scope.indent = function () {
            var childElem = angular.element(element.children()[0]);

            if (scope.content.indentLevel < 3) {
                childElem.removeClass("indent_" + scope.content.indentLevel);
                childElem.addClass("indent_" + (scope.content.indentLevel + 1));
                scope.content.indentLevel++;
                // update Database
                // indent child nodes?
                // for (var i=0; i < nodes; i++) {                      }

            }
        };


    };

    return {
        restrict: "E",
        link: linker,
        scope: {
            content: '='
        }
    };
});

我想在AngularJS建立一个待办事项应用程序使用嵌套的待办事项。作为其中的一部分,我想升级或降级任务与点击的能力(最终,它将一个'标签'或'移标签”按键的反应)。当缩进,缩进的功能也应该任何孩子游戏。这就是我有麻烦的地方。我不知道如何在指令中实现递归函数。如果有人看到这样做或提供任何帮助,我将不胜感激。我创建了一个工作,一个做JSFiddle缩进但不缩进它的孩子。JS Fiddle在这里https://jsfiddle.net/t1ba50k6/16/

此外,请提供任何最佳惯例编码公约或清理指令。

谢谢!

我的HTML:

<ul id=Todos ng-app="app" ng-controller="todos">
    <div ng-repeat='todo in model' ng-init="todoIndex = $index">
       <todo-item content="todo"></todo-item>
    </div>

我的JavaScript:

var app = angular.module('app', []);

app.controller("todos", function ($scope) {

    $scope.model = [{
        "title": "Task item one",
            "indentLevel": 1
    }, {
        "title": "Task item two",
            "indentLevel": 2
    }, {
        "title": "Task item three",
            "indentLevel": 2
    }];

});


app.directive('todoItem', function ($compile) {

    var getTemplate = function (content) {
        var startStr = '';
        var endStr = '';

        if (content.indentLevel == 1) {
            startStr = '<li class="todolist"><table><tr><td><div class="checkboxpadding"><img width="16" height="16" class="checkbox"></div></td><td><div ng-click="indent()">';
            endStr = '</div></td></tr></table></li>';

            return startStr + content.title + endStr;
        } else if (content.indentLevel == 2) {

            startStr = '<li class="todolist indent_2""><table><tr><td><div class="checkboxpadding"><img width="16" height="16" class="checkbox"></div></td><td><div ng-click="indent()">';
            endStr = '</div></td></tr></table></li>';
            return startStr + content.title + endStr;
        }


    };

    var linker = function (scope, element, attrs) {

        element.html(getTemplate(scope.content)).show();
        $compile(element.contents())(scope);


        scope.indent = function () {
            var childElem = angular.element(element.children()[0]);

            if (scope.content.indentLevel < 3) {
                childElem.removeClass("indent_" + scope.content.indentLevel);
                childElem.addClass("indent_" + (scope.content.indentLevel + 1));
                scope.content.indentLevel++;
                // update Database
                // indent child nodes?
                // for (var i=0; i < nodes; i++) {                      }

            }
        };


    };

    return {
        restrict: "E",
        link: linker,
        scope: {
            content: '='
        }
    };
});
answer1: 回答1:

Mapping your data to a nested structure would greatly simplify this.

Always use the same property names for the child arrays:

$scope.model = [{
        "title": "Task item one",
        "indentLevel": 1,
        "children": [
            {
              "title": "Task item two",
              "indentLevel": 2,
               "children":[]
            }, {
               "title": "Task item three",
               "indentLevel": 2,
                "children":[]
            }
        ]
}];

将数据映射到嵌套结构将大大简化此。

总是为子数组使用相同的属性名称:

$scope.model = [{
        "title": "Task item one",
        "indentLevel": 1,
        "children": [
            {
              "title": "Task item two",
              "indentLevel": 2,
               "children":[]
            }, {
               "title": "Task item three",
               "indentLevel": 2,
                "children":[]
            }
        ]
}];
answer2: 回答2:

One solution is using $broadcast(name, args) and $on(name, listener) of scope.

when cliked fire an event:

scope.$broadcast('indent');

in child directives,

scope.$on('indent', scope.indent);

一种解决方案是使用$广播(名称,args)和美元(名称、听众)范围。

当cliked火灾事件:

scope.$broadcast('indent');

在儿童指令,

scope.$on('indent', scope.indent);
angularjs  coding-style