Search code examples
javascriptangularjsangularjs-directiveangular2-styleguide

angularjs directive use controller as vm instead of scope


I am attempting to create a directive. I have been following the john papa opinionated style guide and using controller as vm. unfortunately when I attempt to make a directive I am unsure how to do it without using $scope instead of vm.

(the last tag should say angularjs-styleguide but I couldn't find one and I don't have enough points to make a new tag)

here is the plunkr. https://plnkr.co/edit/DYTJURgaLd0QadcCSPFW?p=preview

<script src="https://code.angularjs.org/1.5.5/angular.js"></script>
<script src="./script.js"></script>
<script src="./directive.js"></script>
<div ng-app="myApp">
    <div ng-controller="myCtrl as vm">
       <div unordered-list="products" list-property="price | currency"></div>
       <!-- this does not work
       <div unordered-list="vm.products" list-property="price | currency"></div>
       -->
    </div> 
</div>

controller

(function() {
    'use strict';
angular
  .module('myApp', [])
  .controller('myCtrl', myCtrl);

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

   function myCtrl($scope){
       /* jshint validthis: true */
       var vm=this;
        $scope.products = [
            { name: "Apples", category: "Fruit", price: 1.20, expiry: 10 },
            { name: "Bananas", category: "Fruit", price: 2.42, expiry: 7 },
            { name: "Pears", category: "Fruit", price: 2.02, expiry: 6 },
        ];

        vm.products =  [
            { name: "Apples", category: "Fruit", price: 1.20, expiry: 10 },
            { name: "Bananas", category: "Fruit", price: 2.42, expiry: 7 },
            { name: "Pears", category: "Fruit", price: 2.02, expiry: 6 },
        ];
   } 

})();

directive

angular.module("myApp")
    .directive("unorderedList", function () {
        return {
            link: function (scope, element, attrs) {
                scope.data = scope[attrs["unorderedList"]];
            },
            restrict: "A",
            template: "<ul><li ng-repeat='item in data'>"
            + "{{item.price | currency}}</li></ul>",
            replace: true
        };
    });

Solution

  • If you specify scope: { data: '=unorderedList' } in your directive, angular will automatically pull the value of vm.products into the directive's scope and it will be available under the data variable. Also, there is no need for the link() function.

    angular.module("myApp")
        .directive("unorderedList", function () {
            return {
                scope: { data: '=unorderedList' },
                restrict: "A",
                template: "<ul><li ng-repeat='item in data'>"
                + "{{item.price | currency}}</li></ul>",
                replace: true
            };
        });