简体   繁体   English

具有隔离范围的AngularJS分页指令

[英]AngularJS Pagination Directive w/ Isolate Scope

I have the following pagination directive written by a member of my team: 我的团队成员编写了以下分页指令:

myApp.directive('pagination', function($timeout) {
    return {
        restrict: 'A',
        controller: function($scope, $element, $attrs, $rootScope) {
            var halfDisplayed = 1.5,
                    displayedPages = 3,
                    edges = 2;
            $scope.getInterval = function() {
                return {
                    start: Math.ceil($scope.currentPage > halfDisplayed ? Math.max(Math.min($scope.currentPage - halfDisplayed, ($scope.pages - displayedPages)), 0) : 0),
                    end: Math.ceil($scope.currentPage > halfDisplayed ? Math.min($scope.currentPage + halfDisplayed, $scope.pages) : Math.min(displayedPages, $scope.pages))
                };
            };
            $scope.selectPage = function(pageIndex) {
                $scope.currentPage = pageIndex;
                $scope.$apply();
                $scope.draw();
                $scope.paginationUpdate();
            };
            $scope.appendItem = function(pageIndex, opts) {
                var options, link;

                pageIndex = pageIndex < 0 ? 0 : (pageIndex < $scope.pages ? pageIndex : $scope.pages - 1);

                options = $.extend({
                    text: pageIndex + 1,
                    classes: ''
                }, opts || {});

                if (pageIndex === $scope.currentPage) {
                    link = $('<span class="current">' + (options.text) + '</span>');
                } else {
                    link = $('<a href="javascript:void(0)" class="page-link">' + (options.text) + '</a>');
                    link.bind('click', function() {
                        $scope.selectPage(pageIndex);
                    });
                }

                if (options.classes) {
                    link.addClass(options.classes);
                }

                $element.append(link);
            };
            $rootScope.draw = function() {
                $($element).empty();
                var interval = $scope.getInterval(),
                        i;

                // Generate Prev link
                if (true) {
                    $scope.appendItem($scope.currentPage - 1, {
                        text: 'Prev',
                        classes: 'prev'
                    });
                }

                // Generate start edges
                if (interval.start > 0 && edges > 0) {
                    var end = Math.min(edges, interval.start);
                    for (i = 0; i < end; i++) {
                        $scope.appendItem(i);
                    }
                    if (edges < interval.start) {
                        $element.append('<span class="ellipse">...</span>');
                    }
                }

                // Generate interval links
                for (i = interval.start; i < interval.end; i++) {
                    $scope.appendItem(i);
                }

                // Generate end edges
                if (interval.end < $scope.pages && edges > 0) {
                    if ($scope.pages - edges > interval.end) {
                        $element.append('<span class="ellipse">...</span>');
                    }
                    var begin = Math.max($scope.pages - edges, interval.end);
                    for (i = begin; i < $scope.pages; i++) {
                        $scope.appendItem(i);
                    }
                }

                // Generate Next link
                if (true) {
                    $scope.appendItem($scope.currentPage + 1, {
                        text: 'Next',
                        classes: 'next'
                    });
                }
            };
        },
        link: function(scope, element, attrs, controller) {
            $timeout(function() {
                scope.draw();
            }, 2000);
            scope.$watch(scope.paginatePages, function() {
                scope.draw();
            });
        },
        template: '<div class="pagination-holder dark-theme">' + '</div>',
        replace: true
    };
});

Unfortunately, when he wrote it, the directive refered to controller variables and functions: 不幸的是,当他编写它时,该指令引用了控制器变量和函数:

function PatientListModalConfigCtrl($scope, $rootScope, myService) {
    $scope.currentPage = 0;
    $scope.paginationUpdate = function() {
        var list = myService.search($scope.currentPage + 1);
        list.then(function(data) {
            $rootScope.List = data[1];
            $rootScope.pages = data[0];
        });
    };
};

I was able to replace the function call with $scope[](); 我可以用$scope[]();替换函数调用$scope[](); using the attr parameter, but as soon as I try to add: 使用attr参数,但是一旦我尝试添加:

scope: {
    currentPage: '=',
    totalPages: '='
}

into the directive and isolate the directive from the controller, the pagination stops displaying altogether. 进入指令并将指令与控制器隔离开,分页将完全停止显示。 Can I use the attr parameter for these two variables as well? 我也可以对这两个变量使用attr参数吗? I would prefer to use the scope in the directive because the variables will be changing, but my attempts have failed. 我宁愿在指令中使用作用域,因为变量将更改,但是我的尝试失败了。 I would appreciate any feedback. 我将不胜感激任何反馈。

Unfortunately, I have to say the whole directive looks a bit poorly designed. 不幸的是,我不得不说整个指令的设计看起来有些糟糕。 The dependancy on $rootScope is a big code smell, so is all the injecting of HTML in the controller. 对$ rootScope的依赖是一个很大的代码异味,因此在控制器中注入HTML的情况也是如此。

To get on topic, you are two-way binding to primitives (integers). 要开始讨论主题,您需要双向绑定到基元(整数)。 I am not entirely sure that's your entire problem, but it won't work as you expect. 我不能完全确定这是您的全部问题,但无法按您期望的那样工作。 It's very logical once you think about it, how could AngularJS ever put any data back into (ie update) a primitive? 一旦考虑了一下,这是非常合乎逻辑的,AngularJS如何将任何数据放回到原语中(即更新)?

By the look of it, you don't actually want two-way binding, you just need to send in some values. 从外观上看,您实际上并不需要双向绑定,只需要发送一些值即可。 For such simple data you can define them as attributes ('@'), and then use attrs.$observe() to listen to the changes. 对于此类简单数据,您可以将它们定义为属性('@'),然后使用attrs。$ observe()侦听更改。 As for the HTML, you can then use current-page="{{currentPage}}" to pass in the value (please note, it will be as a string, which you can then parse back). 对于HTML,您可以使用current-page="{{currentPage}}"传递值(请注意,它将作为字符串,然后可以解析回去)。

Another option could be to pass in an object (using two-way binding). 另一种选择是传递对象(使用双向绑定)。 Example: 例:

page = {
    currentPage: 3,
    totalPages: 14
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM