Reputation: 483
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
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
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