user2516186
user2516186

Reputation: 483

Angular: How to encapsulate logic in a directive?

I wonder how I can encapsulate functionality inside of an angular directive according to Rober C. Martin's "Clean Code" book. I want to omit comments and use functions with speaking names instead.

Imagine this code:

app.directive('myDirective' function() {

return  {
    link: function(scope) {

        // initialize visual user state
        scope.visualUserState = { 
             // some very detailed state initialization 
        } 
    }
})

To encapsulate the load functionality, I would like to replace this code like this:

app.directive('myDirective' function() {

return  {
    link: function(scope) {

        scope.initializeVisualUserState = function() {
            scope.visualUserState = { 
               // some very detailed state initialization 
            }
        }


        scope.initializeVisualUserState();

    }
})

What I do not like on the second approach is that "loadDataFromServer" is some functionality that is only used by the link function and not by the view, so I violate the rule that scope should only hold data and functions that is used to interact with the view.

Also the code is not very readable I think.

As the functionality handles very private stuff of the directive, I think that using and injecting a service is not the right way to go.

What would be a better practice to encapsulate this functionality?

Upvotes: 0

Views: 1392

Answers (2)

Naveen
Naveen

Reputation: 830

(function(module){
    module.directive('myDirective', myDirective);

function myDirective(){
  var directive = {
   link : link,
   scope : {state : '='},
   restrict : 'EA',
   template : //Some template which uses state
  }
  return directive;

  function link(){

  }
};

module.controller('myController', myController);
myController.$inject = ['$scope', 'OtherService'];

function myController(scope, service){
  //service is used to pull the data and set to $scope.userState.
}
})(angular.module('myApp'))

And your directive will be :

<myDirective state="userState"></myDirective>

Let me know if this helps.

Upvotes: 0

Pjetr
Pjetr

Reputation: 1382

You should use a controller to add logic to your directive. In your controller you can inject Services. It's best to write a service for a single purpose, and simply let your controller call the services.

In fact you should only use the link function if you need to have your DOM-node, which is actually pretty close to never.

Read the styleguide by John Papa

angular.module('myModule', []);

// Controller
(function() {
  angular
    .controller('myModule')
    .controller('MyController', ['$scope', 'DataService', function($scope, DataService) {
      DataService
        .retrieveData()
        .then(function(data) {
          $scope.visualUserState = data;
        });
    }]);
})();

// Directive
(function() {
  angular
    .module('myModule')
    .directive('myDirective', function() {
      return {
        'restrict': 'E',
        'scope': true,
        'controller': 'MyController',
        'controllerAs': '$ctrl'
      };
    });
})();

Upvotes: 2

Related Questions