Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Have AngularJS inject dependencies into objects like it already does for controllers

I'm using AngularJS 1.0.2 with jQuery 1.8.2 and I'm trying to have AngularJS inject dependencies into objects, like it does for controllers. You can find a basic example on jsFiddle, in there you'll find two controllers (List and NewItem), an object (Item) and a module with a service (named services and communication respectively).

My problem is with Item:

var Item = function (name, price) {
    var self = this;

    self.name = name;
    self.price = price;

    self.pretty = function () {
        return self.name + ": " + self.price;
    };
};

In it I need to use some things outside, let's say I want the pretty method to format the price property to a currency-aware string:

self.pretty = function () {
    return self.name + ": " + $filter("currency")(self.price);
};

But this won't work, as $filter is not defined. (Mind you, the usage of $filter is only an example, it could be anything.)

And modifying var Item = function (name, price) { to var Item = function ($filter, name, price) { won't work too, as it's not AngularJS who's creating the object (as in the case of the controllers), it's me.

So, how can I have AngularJS create the object for me, or have it resolve the dependency I need?

Something like var item = angular.create(Item, $scope.name, $scope.price); or var item = new Item(angular.inject("filter"), $scope.name, $scope.price); I think...

like image 475
Albireo Avatar asked Nov 15 '12 10:11

Albireo


1 Answers

It is possible to ask AngularJS to instantiate your own objects (and inject dependencies into them!) by using the $injector service and its instantiate(Type, locals) method.

For example, given a constructor like this:

var Item = function ($filter, name, price) {
    var self = this;

    self.name = name;
    self.price = price;

    self.pretty = function () {
        return $filter('json')(self);
    };
};

one could create an instance of Item like so:

var item = $injector.instantiate(Item, { name: $scope.name, price: $scope.price });

Please note that the instantiate method accepts 2 arguments:

  • Type: a constructor function.
  • locals: a hash of values that should not be injected but rather taken as-is.

Here is a working jsFiddle (a simplified version of the initial one).

like image 166
pkozlowski.opensource Avatar answered Nov 07 '22 02:11

pkozlowski.opensource