Pull to refresh

Директива для отображения дерева на AngularJS

Занимаюсь разработкой веб-приложения. Столкнулся с необходимостью отображать древовидные данные. При беглом поиске в Google наткнулся на Angular Treeview. Свою задачу выполняет, но хотелось бы большей свободы при кастомизации элементов дерева.
Дальнейшие поиски ожидаемых результатов не дали. Вот так и появилось желание написать свой Treeview для AngularJS.

Html:
<div>
    <ul my-treeview>
        <li ng-repeat="item in items" my-treeview-childs="item.childrens">
            <span ng-click="say(item.id)" ng-class="{ bold: item.id % 2}">{{item.id}} {{item.name}}</span></li>
    </ul>
</div>




Javascript:
$scope.items = [
        { id: 1, name: 'First', childrens: [
            { id: 3, name: 'three', childrens: null },
            { id: 4, name: 'four', childrens: [
                { id: 5, name: 'five', childrens: null }
            ]
            }
        ]
        },
        { id: 2, name: 'second', childrens: [] }
    ];
$scope.say = function (str) {
        alert(str);
    }


Исходный код директивы:
var app = angular.module('myTreeview', []);

app.controller('myTreeviewCtrl', ['$scope', function ($scope) {

} ])

//объявляет дерево
app.directive('myTreeview', [function () {
    return {
        restrict: 'A',
        priority: 1001,
        controller: 'myTreeviewCtrl',
        compile: function (element, tAttrs) {
            //создаем шаблон для дочерних элементов
            angular.forEach(angular.element(element.find('li')), function (item) {
                var el = angular.element(item);

                el.prepend($('<i />').addClass('normal').attr('ng-hide', 'config.hasChildrens'));
                el.prepend($('<i />').addClass('expanded').attr('ng-show', 'config.hasChildrens && !config.collapsed').attr('ng-click', 'collapse(config)'));
                el.prepend($('<i />').addClass('collapsed').attr('ng-show', 'config.hasChildrens && config.collapsed').attr('ng-click', 'collapse(config)'));
            });

            var itemTemplate = element.html();
            var template = $('<ul ng-hide="config.collapsed" />').append(itemTemplate)[0].outerHTML;

            return function (scope, element, attrs, ctrl) {
                //делаем доступным шаблон для дочерней дерективы
                ctrl.Template = template;
                element.addClass('treeview');
                scope.collapse = function (config) {
                    config.collapsed = !config.collapsed;
                }

            }
        }
    }
} ])

//достраивает дочерние элемент
.directive('myTreeviewChilds', ['$compile', '$parse', function ($compile, $parse) {
    return {
        restrict: 'A',
        require: '^myTreeview',
        link: function (scope, element, attrs, ctrl) {
            //достаем дочерние элементы
            var items = $parse(attrs.myTreeviewChilds)(scope);
            var newScope = scope.$new();
            newScope.items = items
            scope.config = {};
            if (items != null && items.length > 0) {
                newScope.$parent.config.hasChildrens = true;
                newScope.$parent.config.collapsed = false;
                element.append($compile(ctrl.Template)(newScope));
            }
            else {
                newScope.$parent.config.hasChildrens = false;
                newScope.$parent.config.collapsed = false;
            }
        }
    }
} ])




Как видно из примера, программист сам контролирует шаблон элементов дерева, что дает большую гибкость при настройке представления.
При разработке были использованы материалы с http://angular.ru, http://angularjs.org и Angular Treeview(css и картинки). А так же вдохновением послужил пост пользователя esvit Директива для работы с таблицами на AngularJS. Надеюсь, кому-нибудь пригодится данное решение. Так же буду рад замечаниям и предложениям. Ссылка на исходники.
Спасибо за внимание.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.