AngularJS指令访问控制器范围

时间:2015-12-22 14:47:17

标签: angularjs angular-directive

TL; DR 我解决了我的问题。这里有三种不同的解决方案:

http://plnkr.co/edit/E0ErKs?p=preview

我不喜欢slider1,因为它在$ scope({{sliderValue}})中存储了值,并且根据Angular Style Guide的推荐,我们应该避免这种情况。

我不喜欢slider2,因为它假定controler在视图中有别名vm(所以我们在视图和指令之间创建某种耦合)。

解决方案3对我来说很合适。我错过了什么吗?

你如何以不同的方式写出这个指令以符合Angular哲学?

初步问题:

我正在学习角度,但对我来说并非一切都很清楚。

我发现了这个问题: How to use jQuery in AngularJS

所以我创建了工作示例:

指令:

(function() {
    'use strict';

    angular.module('demoApp').directive('slider', function () {
        return {
            restrict: 'A',
            controller: function ($scope, $element, $attrs) {
                $scope.onSlide = function (e, ui) {
                    $scope.sliderValue = ui.value;
                    $scope.$digest();
                };
            },
            link: function (scope, el, attrs) {
                var options = {
                    value: scope.sliderValue,
                    slide: scope.onSlide  
                };

                // set up slider on load
                angular.element(document).ready(function () {
                    scope.$slider = $(el).slider(options);
                });
            }
        }
    });
})();

控制器:

(function() {
    'use strict';

    angular.module('demoApp').controller('DemoAppTestCtrl', DemoAppTestCtrl);

    DemoAppTestCtrl.$inject = [ '$scope' ];

    function DemoAppTestCtrl($scope) {
        $scope.sliderValue = 10;
    }
})();

和Html页面:

<div ng-controller="DemoAppTestCtrl as vm">
    Value: {{sliderValue}}
    <div slider></div>
</div>

一切正常。 Angular put滑块代替&lt; div slider&gt;我可以移动它,我会在{{sliderValue}}中看到更改值。

然后我找到了这个角度风格指南 https://github.com/johnpapa/angular-styleguide

在关于控制器的章节中,他们建议使用带有vm语法的controllerAs(因为$ scope是坏的或者是什么)。

例如:

function CustomerController() {
    var vm = this;
    vm.name = {};
    vm.sendMessage = function() { };
}

所以我把控制器改成了这个:

(function() {
    'use strict';

    angular.module('demoApp').controller('DemoAppTestCtrl', DemoAppTestCtrl);

    DemoAppTestCtrl.$inject = [ ];

    function DemoAppTestCtrl($scope) {
        var vm = this;

        vm.sliderValue = 10;
    }
})();

和Html页面:

<div ng-controller="DemoAppTestCtrl as vm">
    Value: {{vm.sliderValue}}
    <div slider></div>
</div>

但我不知道如何解决我的指示。 我想要相同的功能,当我移动滑块时我想在控制器内设置vm.sliderValue而不是范围内的$ scope.sliderValue。

EDIT1:

我能够通过在控制器和链接函数中添加$ scope.vm来使其工作(因为我的控制器在作为vm的范围内)。但我不确定这是否是正确的方法,因为现在我的指令假设在$ scope.vm别名下有范围内的控制器。

这是不好的设计还是正常的Angular服务方式?

(function () {
    'use strict';

    angular
        .module('demoApp')
        .directive('slider', slider);

    slider.$inject = [ ];

    function slider() {
        return {
            restrict: 'A',
            controller: function ($scope, $element, $attrs) {
                $scope.vm.onSlide = function (e, ui) {
                    $scope.vm.sliderValue = ui.value;
                    $scope.$digest();
                };
            },
            link: function (scope, el, attrs) {
               var options = {
                   value: scope.vm.sliderValue,
                   slide: scope.vm.onSlide  
               };

               // set up slider on load
               angular.element(document).ready(function () {
                   scope.$slider = $(el).slider(options);
               });
            }
         }
    }
})();

EDIT2:

我能够创建具有3个不同版本的工作Plunker: http://plnkr.co/edit/E0ErKs?p=preview

2 个答案:

答案 0 :(得分:0)

答案 1 :(得分:0)

尝试这样的事情:

&#13;
&#13;
angular.module('myApp', []);

angular.module('myApp').controller('DemoAppTestCtrl', DemoAppTestCtrl);

function DemoAppTestCtrl() {
	var vm = this;
	
  vm.sliderValue = 10;
}

angular.module('myApp').directive('slider', sliderDirective );

function sliderDirective() {
	return {
  	restrict: 'A',
    controller: sliderController,
    controllerAs: 'sliderCtrl',
    template: "<p>{{sliderCtrl.test}}</p>"
  }
}

function sliderController() {
	var vm = this;
  
  vm.test = "hello";
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="DemoAppTestCtrl as vm">
    Value: {{vm.sliderValue}}
    <div slider></div>
</div>
</div>
&#13;
&#13;
&#13;