allencoded
allencoded

Reputation: 7275

Javascript Getter/Setter in Angular Service with 2 Controllers

I am messing with javascript getters and setters in my service layer. I am using 2 controllers. The first controller just displays some text. The second controller allows hiding it. I am trying to figure out why one method works while another does not.

Here is the working example:

var app = angular.module('plunker', []);

app.factory('data', function () {
  var fac = [];
  var state = false;

  fac.hideIt = function (hide) {
    state = hide;
  };

  fac.hidden = function() {
    return state;
  }

  return fac;
});

app.controller('MainCtrl', function($scope, data) {
  $scope.name = 'World';
  $scope.hide = data.hidden;
});

app.controller('SecCtrl', function($scope, data) {
  $scope.hideAbove = function () {
    var hide = true;
    data.hideIt(hide);
  };
});

Here is the not working example:

var app = angular.module('plunker', []);

app.factory('data', function () {
  var fac = [];

  fac.hide = {
                state: false, 
                get get() {
                  return this.state
                }, 
                set set(hide) {
                  return this.state = hide;
                }
              };

  return fac;
});

app.controller('MainCtrl', function($scope, data) {
  $scope.name = 'World';

  $scope.hide = data.hide.get;
});

app.controller('SecCtrl', function($scope, data) {

  $scope.hideAbove = function () {
    var hide = true;
    data.hide.set = hide;
    console.log(data.hide.get)
  }
});

HTML (shared by both)

<body>
    <div ng-controller="MainCtrl">
      <div ng-hide="hide()">
        <p>Hello {{name}}!</p>
      </div>
    </div>

    <div ng-controller="SecCtrl">
      <div ng-click="hideAbove()">CLICK HERE </div>
    </div>  

  </body>

So my question is why does using the getter and setters in the non-working block of code not work?

Upvotes: 1

Views: 7407

Answers (2)

Rahil Wazir
Rahil Wazir

Reputation: 10132

See in your html:

ng-hide="hide()"

The problem is simple you need to change hide property into method inside MainCtrl

$scope.hide = function() {
    return data.hide.get;
}

DEMO

But you will say why the first example worked?

Because in the first example data.hidden does return function literal while the latter example just returns the value from getter.

Upvotes: 1

Ben Guest
Ben Guest

Reputation: 1558

You should use a service rather than a factory for this. A factory's value is set to the return value of the function you pass to it. There is not really a concept of "this" in a factory ("this" probably points to the window object). "this" in a service points to the service instance.

app.service('data', function () {
  this.state = false;

  this.hide = {
      get value() {
          return this.state;
      },
      set value(hide) {
          this.state = hide;
      }
  };
});

Upvotes: 3

Related Questions