0

TL;DR I solved my problem. Here is plunker with 3 different solutions:

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

I don`t like slider1 because it stores value in $scope ( {{sliderValue}} ) and according to recommendation from Angular Style Guide we should avoid that.

I don`t like slider2 because it assumes that controler have alias vm in a view (so we create some kind of coupling between view and directive).

Solution 3 looks OK for me. Am I missing something?

How would you write differently this directive to be in complience with Angular philosophy?


INITIAL QUESTION:

I am learning angular and not everything is clear to me yet.

I found this question: How to use jQuery in AngularJS

So I created working example:

Directive:

(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);
                });
            }
        }
    });
})();

Controller:

(function() {
    'use strict';

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

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

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

And Html page:

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

Everything works fine. Angular put slider in place of <div slider> and I can move it and I see changing values in {{sliderValue}}.

Then I found this Angular Style Guide https://github.com/johnpapa/angular-styleguide

In chapter about controllers they recommend to use controllerAs with vm syntax (because $scope is bad or something).

Ex:

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

So I changed my controller to this:

(function() {
    'use strict';

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

    DemoAppTestCtrl.$inject = [ ];

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

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

And Html page to:

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

But i don`t know how to fix my directive. I want the same functionality, when i move the slider i want to set vm.sliderValue inside controler instead $scope.sliderValue inside scope.

EDIT1:

I was able to make it work by adding $scope.vm inside controller and link functions (because my controller sits in scope as vm). But I am not sure if this is right way to do it, because now my directive assume that there is controller in scope under $scope.vm alias.

Is this bad design or normal way of doing things in 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:

I was able to create working Plunker with 3 different versions: http://plnkr.co/edit/E0ErKs?p=preview

2 Answers 2

0

Use scope: false as a option in the directive.

http://www.undefinednull.com/2014/02/11/mastering-the-scope-of-a-directive-in-angularjs/

Sign up to request clarification or add additional context in comments.

2 Comments

But as I understand the scope: false causes that directive uses its parent scope. But i dont use $scope in my new version of controller. Instead I am storing sliderValue inside Controller (not in scope). So my question is how to set value inside this controller from directive (since this is now recommended way of writing controllers).
Do like this: <div slider="vm.sliderValue"></div> and then in the link function you can access this variable in attrs.slider
0

try something like this:

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";
}
<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>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.