Zhao Xiang
Zhao Xiang

Reputation: 1643

Subclass factory in AngularJS with member variables

I have tens of AngularJS Factories which have a lot in common. So I'm trying to make a base class and subclass it.

But I've noticed that the subclasses are sharing member variables of the base class.

I've made an example on http://jsbin.com/doxemoza/2/edit, the code is also posted here:

HTML:

<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.3/angular.min.js"></script>
<meta charset=utf-8 />
<title>JS Bin</title>
</head>
<body ng-app="demo" ng-controller="MainCtrl">
  <p>ChildService: {{value1}}</p>
  <p>AnotherChildService : {{value2}}</p>
</body>
</html>

JavaScript:

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

var demo = angular.module('demo').controller('MainCtrl', function ($scope, ChildService, AnotherChildService) {
  $scope.value1 = ChildService.getPrivateVar();
  $scope.value2 = AnotherChildService.getPrivateVar();
});

var Base = function () {

  var Service = {};

  Service.privateVar = 0;

  Service.setPrivateVar = function (value) {
    Service.privateVar = value;
  }

  Service.getPrivateVar = function () {
    return Service.privateVar;
  }

  return Service;
};

demo.factory('BaseService', Base)


demo.factory('ChildService', function (BaseService) {
  var ChildService = Object.create(BaseService);
  ChildService.setPrivateVar(1);
  return ChildService;
});

demo.factory('AnotherChildService', function (BaseService) {
  var AnotherChildService = Object.create(BaseService);
  AnotherChildService.setPrivateVar(2);
  return AnotherChildService;
});

My expected output is:

ChildService: 1

AnotherChildService : 2

But instead I get:

ChildService: 2

AnotherChildService : 2

I think ChildService and AnotherChildService are sharing the same privateVar, so I got the same value for them.

How should I change the code to make them use different instance of privateVar?

Thanks

Upvotes: 3

Views: 1495

Answers (2)

Lucas
Lucas

Reputation: 134

I had that same problem, and was solved when a declared my BaseService this way:

demo = angular.module('demo', []);

demo.factory('BaseService', function(){
  return {
    privateVar: 0,

    setPrivateVar: function (value) {
      this.privateVar = value;
    },

    getPrivateVar: function () {
        return this.privateVar;
    }
  }
});

My "child" services are like yours. Everything works very fine.

Upvotes: 1

Raphael M&#252;ller
Raphael M&#252;ller

Reputation: 2200

I use something like this:

angular.module('app')
.controller('ParentController', ['$scope', 'dataService', function ($scope, dataService) {
   //controller logic here
}])
.controller('ChildController', ['$scope', '$controller', 'SomeDataService', function ($scope, $controller, SomeDataService) {
//extend your parentcontroller
    $scope.init = function () {
        //do something
    }
    angular.extend(this, $controller('ParentController', {
        $scope: $scope,
        dataService: SomeDataService
    }));
}])
.factory('BaseDataService', ['logger', function (logger) {
  var privateArray = [];

  return {
   publicFunction: function(){ return privateArray; },
   publicVar: "some var"
  }
}])
.factory('SomeDataService', ['BaseDataService', function (dataService) {
    var service = angular.extend({}, dataService);
    service.privateFunction = function () {
        //some code
    }
    service.privateVar= "some value";
    return service;
}]);

I combined all of them in this example.

Hope this helps.

Edit: this uses the mixin pattern described in this post

Upvotes: 1

Related Questions