控制器,绑定器和手表



我有一个具有控制器的指令。看起来像这样:

.directive('pkSlider', ['$timeout', function ($timeout) {
    return {
        restrict: 'A',
        scope: {
            question: '=pkSlider',
            options: '=',
            onSelect: '&'
        },
        controller: 'PKSliderController',
        templateUrl: function (element, attrs) {
            if (attrs.type === 'image')
                return 'assets/templates/directives/pk-image.html';
            return 'assets/templates/directives/pk-slider.html';
        },
        link: function (scope, element, attrs, controller) {
            // Get our visible answers
            scope.answers = controller.getVisibleAnswers(scope.question.answers);
            // Increase the answers if they are less than the slides to show
            if (scope.answers.length <= scope.options.slidesToShow)
                scope.answers = scope.answers.concat(scope.answers);
            // Watch our answers
            scope.$watch('answers', function (answers) {
                // When we have our answers
                if (answers.length) {
                    // Extend our options
                    angular.extend(scope.options, {
                        event: {
                            // Set our first slide and sort/filter our products
                            init: function (event, slick) {
                                // Get the actual index stored in the answer
                                var index = scope.answers[slick.currentSlide].index;
                                // Set our current slide to the physical current slide, this is for the images to be shown
                                scope.currentSlide = slick.currentSlide;
                                // Invoke our methods using the answer index
                                controller.afterChange(scope.question, index);
                                scope.onSelect({ index: index, direction: slick.direction });
                            },
                            // Set our current slide and sort/filter our products
                            afterChange: function (event, slick, currentSlide) {
                                // Get the actual index stored in the answer
                                var index = scope.answers[currentSlide].index;
                                // Set our current slide to the physical current slide, this is for the images to be shown
                                scope.currentSlide = currentSlide;
                                // Invoke our methods using the answer index
                                controller.afterChange(scope.question, index);
                                scope.onSelect({ index: index, direction: slick.direction });
                            }
                        }
                    });
                    // We have loaded
                    scope.loaded = true;
                }
            });
        }
    };
}]);

,控制器看起来像这样:

.controller('PKSliderController', ['$timeout', '$interval', 'TrackingProvider', 'AnswerProvider', function ($timeout, $interval, tracking, provider) {
    var self = this,
        timer,
        setActiveImage = function (answers, activeIndex) {
            // If we have a current timer running, cancel it
            if (timer)
                $timeout.cancel(timer);
            // For each answer
            answers.forEach(function (answer, index) {
                // Get our images
                var images = answer.images;
                // If we have an image
                if (images) {
                    // Get our image
                    var image = images[0];
                    // If we are active
                    if (index === activeIndex) {
                        // For each text
                        image.imageText.forEach(function (text) {
                            text.active = false;
                            // Activate our text after the delay
                            $interval(function () {
                                text.active = true;
                            }, text.delay, 1);
                        });
                    }
                }
            });
        };
    // Get our answers
    self.getVisibleAnswers = provider.getVisible;
    // Updates the question with your selected answer
    self.afterChange = function (question, answerIndex) {
        // Get our answer
        var answers = question.answers,
            answer = answers[answerIndex];
        // Set our active image
        setActiveImage(answers, answerIndex);
        // This is for the last step, because some options might not actually be available
        if (answer) {
            // Set our selected answer
            question.radioChoice = answer.text;
        }
    };
}])

我一直在根据"角样式指南"转换我的代码,并找到了一个我没有意识到的指令的新选项,称为 bindtocontroller 。因此,我正在尝试实施这一点。我已经将指示转换为:

(function () {
    'use strict';
    angular.module('widget.directives').directive('pkSlider', pkSlider);
    pkSlider.$inject = ['$timeout'];
    function pkSlider($timeout) {
        return {
            restrict: 'A',
            scope: {
                question: '=pkSlider',
                options: '=',
                onSelect: '&'
            },  
            controller: 'PKSliderController',
            controllerAs: 'controller',
            bindToController: true,
            templateUrl: getTemplate
        };
        function getTemplate(element, attrs) {
            if (attrs.type === 'image')
                return 'app/directives/pkImage.html';
            return 'app/directives/pkSlider.html';
        };
    }
})();

这已经更加干净了。然后,我尝试转换我的控制器:

(function () {
    'use strict';
    angular.module('widget.directives').controller('PKSliderController', PKSliderController);
    PKSliderController.$inject = ['$scope', '$timeout', '$interval', 'answerProvider'];
    function PKSliderController($scope, $timeout, $interval, answerProvider) {
        var self = this,
            timer;
        // Bindings
        self.afterChange = afterChange;
        $scope.$watch('controller.answers', watchAnswers);
        // Init
        init();
        function init() {
            // Get our answersw
            self.answers = answerProvider.getVisible(self.question.answers);
            // Increase the answers if they are less than the slides to show
            if (self.answers.length <= self.options.slidesToShow)
                self.answers = self.answers.concat(self.answers);
        };
        // Watches the answers for any changes
        function watchAnswers(answers) {
            // When we have our answers
            if (answers.length) {
                // Extend our options
                self.options = angular.merge(self.options, {
                    event: {
                        // Set our first slide and sort/filter our products
                        init: function (event, slick) {
                            // Get the actual index stored in the answer
                            var index = self.answers[slick.currentSlide].index;
                            // Set our current slide to the physical current slide, this is for the images to be shown
                            self.currentSlide = slick.currentSlide;
                            // Invoke our methods using the answer index
                            controller.afterChange(self.question, index);
                            self.onSelect({ index: index, direction: slick.direction });
                        },
                        // Set our current slide and sort/filter our products
                        afterChange: function (event, slick, currentSlide) {
                            // Get the actual index stored in the answer
                            var index = self.answers[currentSlide].index;
                            // Set our current slide to the physical current slide, this is for the images to be shown
                            self.currentSlide = currentSlide;
                            // Invoke our methods using the answer index
                            controller.afterChange(self.question, index);
                            self.onSelect({ index: index, direction: slick.direction });
                        }
                    }
                });
                // We have loaded
                self.loaded = true;
            }
        };
        // Updates the question with your selected answer
        function afterChange(question, answerIndex) {
            console.log('we are changing');
            // Get our answer
            var answers = question.answers,
                answer = answers[answerIndex];
            // Set our active image
            setActiveImage(answers, answerIndex);
            // This is for the last step, because some options might not actually be available
            if (answer) {
                // Set our selected answer
                question.radioChoice = answer.text;
            }
        };
        // Sets the active image
        function setActiveImage(answers, activeIndex) {
            // If we have a current timer running, cancel it
            if (timer)
                $timeout.cancel(timer);
            // For each answer
            answers.forEach(function (answer, index) {
                // Get our images
                var images = answer.images;
                // If we have an image
                if (images) {
                    // Get our image
                    var image = images[0];
                    // If we are active
                    if (index === activeIndex) {
                        // For each text
                        image.imageText.forEach(function (text) {
                            text.active = false;
                            // Activate our text after the delay
                            $interval(function () {
                                text.active = true;
                            }, text.delay, 1);
                        });
                    }
                }
            });
        };
    };
})();

,但我对手表有问题。它似乎不会更改选项。我已经将选项添加到我的视图中,它返回了以下内容:

{" slidestoshow":1," centerpadding":0," event":{}}

这很有趣,因为我只通过了:

{slidestoshow:1,centerpadding:0}

因此,它正在更新,但实际上并未将方法绑定到事件对象。有人知道为什么甚至如何使此工作工作吗?

您需要在self.answers上观看,因为它可以在控制器实例上直接使用thisself如下:

$scope.$watch(angular.bind(self, function () {
  return self.answers;
}), watchAnswers);

这是我的错,它正确创建了所有内容。在视图中,我没有将其绑定到"控制器"。

最新更新