0

Say I have this base provider:

angular.module('app').provider('BaseClient', function () {
    this.setSomething = function (something) {
        // Store `something` somewhere
        return this;
    };
});

And now these 2 other sub-providers:

angular.module('app').provider('ClientA', function () {
    this.$get = function () {
        return {
            foo: function () {
                console.log('FOO', /* Read `something`, needs to output 'aaa' */);
            }
        }
    };
});

angular.module('app').provider('ClientB', function () {
    this.$get = function () {
        return {
            bar: function () {
                console.log('BAR', /* Read `something`, needs to output 'bbb' */);
            }
        }
    };
});

angular.module('app').config(function (clientAProvider, clientBProvider) {
    clientAProvider.setSomething('aaa');
    clientBProvider.setSomething('bbb');
});

How do I make ClientA and ClientB inherit the provider section of BaseClient in such a way that I can call clientAProvider.setSomething('aaa') and clientBProvider.setSomething('bbb') and store that value per provider, while using the same setSomething implementation?

I have a bunch of these providers (more than these 2) where the provider section is always the same, the configuration implementation is always the same but the factory section of those providers are different.

Thoughts?

rfgamaral
  • 16,546
  • 57
  • 163
  • 275

1 Answers1

1

You could inject BaseClientProvider into your ClientA provider.

Full code is here plnkr


app.provider('BaseClient', function() {
  this.config = {
    something: null
  };

  this.setSomething = function(something) {
    this.config.something = something;
    return this;
  };

  this.$get = function() {};
});

app.provider('ClientA', ['BaseClientProvider', function(BaseClientProvider) {
  var self = this;
  angular.extend(self, BaseClientProvider);
  self.$get = function() {
    return {
      foo: function() {
        console.log('FOO', self.config.something);
      }
    }
  };
}]);
Steven Weng
  • 322
  • 1
  • 9
  • I'm really sorry but looking at the answer I just realized I made the wrong question. Please give me a few minutes to fix the question. – rfgamaral Jun 18 '15 at 17:28
  • Updated. Sorry again. – rfgamaral Jun 18 '15 at 17:34
  • I add `angular.extend(this, BaseClientProvider);` into `ClientA` provider, It's work. – Steven Weng Jun 18 '15 at 17:56
  • Never thought of using `angular.extend` like that :) I can't really test this right now, but are you sure it works to the point where each client provider will have it's own independent configuration values? That's what the `self` is for, correct? – rfgamaral Jun 18 '15 at 23:15
  • I'm sure. You could see my plunker link. – Steven Weng Jun 19 '15 at 09:07
  • Unfortunately it's not working exactly as expected, see the full plunkr here: http://plnkr.co/edit/wTwHxBvOaTtmVFlKK1IC?p=preview - The problem is `angular.extend` which does not do a deep copy. Using `angular.merge` from v1.4 solves the issue, but I can't use that just yet. Another way to solve the problem is to store each configurable variable at `this.variable` instead of `this.config.variable`. This also solves it. Or am I missing something on your solution and it should work as you posted it? – rfgamaral Jun 19 '15 at 10:00
  • I just remember I'm using `lodash` and I have access to `merge`. – rfgamaral Jun 19 '15 at 10:12
  • But now that I'm implementing this on my real code, I've come to the conclusion that I wanted something slightly different, which I'm not sure it's possible. I'm exposing `this.config` to the public and you could just inject the provider and change `something` by directly changing the `config` object or through the `setSomething` function. I'd prefer if you could only do that through the `setSomething` function. – rfgamaral Jun 19 '15 at 10:17
  • I edit from `angular.extend(self, BaseClientProvider);` to `angular.extend(self, angular.copy(BaseClientProvider));` in your full [plunkr] (http://plnkr.co/edit/AeAI92i26JOPwItX3Tmn?p=preview). Is it working exactly as expected? – Steven Weng Jun 19 '15 at 11:03
  • Yes, that works too, but I'll use `_.merge` instead, it's simpler. What about the problem I described in the previous comment. Do you have any ideas? – rfgamaral Jun 19 '15 at 12:43
  • Sorry, I'm not sure what's your problem. – Steven Weng Jun 19 '15 at 16:14
  • When you inject the provider in the config phase, you can call `setSomething` to set the value of `something`, but you can also just change `config.something` directly. Any way to avoid that and only have the set method changing the value? But still having different config objects per provider. – rfgamaral Jun 19 '15 at 16:28
  • My original problem was solved by this solution and nobody else came up with a better/different one. I'm accepting this as the correct answer and create a new one for the other problem. See here if you're interested: http://stackoverflow.com/questions/30970343/how-to-prevent-direct-access-to-variables-on-this-when-inheriting-from-a-base Thank you. – rfgamaral Jun 21 '15 at 23:32