3

I'm looking for a good design pattern to provide angular directives render acording to some global specified parametrs. For example, I have some factory called "Settings", that holds the value "directiveColor: red". When i do the link in my directive, I ask the Settings about my directiveColor value. Everything is working fine - I got red and put element on the page. But I have hundreds of this elements on the page, and every directive before render ask for settings... I think it's not very good way. What will you recomend?

UPD

factory

app.factory('Settings', function() {
    var data = {
        //...
        directiveColor: red //set by user
    }
    //...
    GetSettings : function () {return data}
}

directve

app.directive('wdMyDirective', ['Settings', function(Settings) {
    return {
        restrict: 'E',
        link: function(scope, elem, attr) {
            scope.data = {
                //...
                color:  Settings.GetSettings().directiveColor
            };
    };
}]);
//later "color" used in template through the scope

That's how it works for now (works fine). But every time, when I render directive (many many times on the page, ngRepeat for table data), my directive ask for Settings to choose its color. I think, it is not good. Or maybe not?

vittore
  • 17,449
  • 6
  • 44
  • 82
  • 1
    Whare is the code to improve? Do you have any performance problem? If not, why do you care? – JB Nizet Sep 06 '15 at 12:52
  • I'm new to angular, but it sounds like defining a service which you can get injected into your directives or on demand would be a good clean soloution. something like $settings – eran otzap Sep 06 '15 at 12:58
  • 2
    @eranotzap the $ prefix is a namespace used by angular to avoid clashes betwee angular-provided services and application services. Application servises should NOT be prefixed by a $. – JB Nizet Sep 06 '15 at 13:04
  • 1
    @JBNizet good to know. thanks i wasn't aware of that. Any thoughts on providing a settings service..? is there a built in service which can be used for this purpose ? – eran otzap Sep 06 '15 at 13:06
  • No, no such service exists. But it seems the user just wants a constant or value. – JB Nizet Sep 06 '15 at 13:12
  • 2
    "I think it's not very good way" is merely your assertion, but you have to, at least, specify what problems (performance, code cleanness / maintenability / flexibility) you foresee and would like to avoid – New Dev Sep 06 '15 at 13:22
  • I've updated the post, please look – georgiy.zhuravlev Sep 06 '15 at 16:08
  • @eranotzap he already have settings service. Factory and Service are the same thing in angular with exception that Service is called with `new`. – vittore Sep 06 '15 at 16:48
  • @vittore when i wrote that comment 4 hours ago he didn't have any code written down :) – eran otzap Sep 06 '15 at 17:16
  • @JBNizet a constant would pollute the global namespace. That potentially might later cause unexpected errors. – eran otzap Sep 06 '15 at 17:18
  • 2
    @eranotzap he is talking about angular thing `angular.module('a').constant(...)` and `angular.module('a').value(...)` – vittore Sep 06 '15 at 17:36

1 Answers1

2

There are two considerations here. First, you are right that it is not optimal, and directive actually provides a way to do that call once, read about Compile-PreLink-PostLink in angular directives. Basically you want this call in Compile step if it is the same for all directives in your app.

Second consideration is that Settings.GetSettings().directiveColor will give really really small overhead if GetSettings() returns just an object that you only create once ( and that is what happened as angular factories are singletons )

In your case you can do

app.factory('Settings', function() {
  var data = {
      directiveColor: 'red' //set by user
  }

  return {
      GetSettings : function () {return data}
  }
})

app.directive('wdMyDirective', ['Settings', function(Settings) {
  return {
    restrict: 'E',       
    compile: function(elem, attrs) {             
        var color = Settings.GetSettings().directiveColor 
        return function postLink(scope, elem, attr) {
           scope.data = {
              color:  color
           };
        }
    }
  }
}])

instead of declaring link property on directive.

Community
  • 1
  • 1
vittore
  • 17,449
  • 6
  • 44
  • 82