2

I would really appreciate some feed back on how this works? I have a service in which I store some session specific variables such as table sorting choices and more.

The code seems to work fine. However, my question is - how is it possible for me to retrieve these values without returning the actual variable?

Shouldn't I have to use some kind of Getter function? Are they made public some way with the setter method, or am I doing something completely wrong here? Is using this some kind of culprit? Or simply my lack of understanding of javascript scoping? :)

Service code:

angular.module('myApp').service('sessionService', function () {

  this.searchView = 2; // <-- edited in, forgot this

  return {
    setSearchView: setSearchView
  };

  function setSearchView (searchView) {
    this.searchView = searchView;
  }

});

And then we have the controller.

angular.module('myApp').controller('SearchCtrl', function (sessionService) {

  console.log(sessionService.searchView); //undefined

  sessionService.setSearchView(1);

  console.log(sessionService.searchView); // 1 

});

Once I've set for example the searchView from the controller, it is possible to just access it as below.

Anything that can help me understand this would be appreciated.

EDIT: I forgot to add that this.searchView was actually there form the start, same result in console.log in the controller though.

Jonas Eriksson
  • 171
  • 4
  • 12
  • The service doesn't have a property named `searchView` until you set it, at which point it is defined and public. If you wanted it to be private, you'd have to use a variable so it is scoped to that function and use getter/setter methods. – Lee Nov 24 '15 at 13:30
  • when the service is initialized, searchView IS undefined, it gets its value only after you use setSearchView – Nitsan Baleli Nov 24 '15 at 13:32
  • Thanks for your answers, please see my edit. this.searchView = 2; was there from the start. Does this make a difference in any way? – Jonas Eriksson Nov 24 '15 at 13:45

2 Answers2

2

Service are what are called 'singletons' meaning you can set a variable not directly accessible or returned and it will maintain it's values for the life if the UI. In this case, if you want t be able to access sessionService.searchView, you can do it a few ways:

1) Set a private var searchView and then add a getter function to your return statement:

  return {
    setSearchView: setSearchView,
    getSearchView: function() {
        return searchView;
    }
  };

2) create the same private variable and then add it to your return statement:

var searchView;

return {
    setSearchView: setSearchView,
    searchView: searchView
};
Brant
  • 1,735
  • 11
  • 18
1

When you inject the service into the controller

angular.module('myApp').controller('SearchCtrl', function (sessionService) {

you are provided with an instance of the service definition function. In other words, your sessionService is basically

new function () {

  return {
    setSearchView: setSearchView
  };

  function setSearchView (searchView) {
    this.searchView = searchView;
  }

}

i.e the function you passed in when you defined the service preceded by new. The new means that you are just using it as a constructor function.


Now, what do we know about new and Javascript constructors - just that if the constructor function returns an object, that's what the left hand side of new is set to. And this in the member methods basically refers to that same object.

In short, your service definition is a constructor function. In plain Javascript it would look something like this.

function SessionService () {
  return {
    setSearchView: function (searchView) {
       this.searchView = searchView;
    }
  };
}

var sessionService = new SessionService();

Notice that I capitalized SessionService to indicate that it is a constructor and sessionService is in camel case because it is an instance.


With this in mind, when you do

sessionService.setSearchView(1);

you are setting the searchView property of the sessionService instance to 1. And when you do

sessionService.searchView

this is the exact same property that you are accessing and you get the value you set.

You could also do sessionService.searchView = 1 and it would work as well, since all you are doing is working on the sessionService instance.

potatopeelings
  • 38,000
  • 6
  • 80
  • 108
  • Thanks for a great answer, however I actually did have a this.searchView = 2; from the start, shouldn't that be a property then? – Jonas Eriksson Nov 24 '15 at 13:48
  • 1
    It would have, IF you hadn't returned anything from the service definition function (knock off the return statement and you'll see it work - you'll have to remove the setSearchView call so that the controller doesn't error out). Check out http://stackoverflow.com/a/3658673/360067 - what's happening is point 4. - your newly created object (the one you set this.searchView to in the first line) is replaced by the non-primitive object that you return. – potatopeelings Nov 24 '15 at 13:56
  • I really appreciate the help, but I might be dense here. I can see it works as you say if I replace this.searchView = 2; with var searchView = 2; So maybe my confusion is more how this.searchView becomes a public property without being explicitly returned... :S – Jonas Eriksson Nov 24 '15 at 14:11
  • 1
    hm.. I actually meant remove the return, like so - http://jsfiddle.net/xk6v5gaq/. – potatopeelings Nov 24 '15 at 14:18
  • 1
    Originally, what's actually returned is the what you return (sorry if that sounds confusing :-)) - i.e. a literal object with just one member function setSearchView. When you call setSearchView (of the object), it in turn sets the property searchView on the object. Your first this.searchView = 2 has no impact because the `this` refers to a separate object, that is discarded in favour of the aforesaid literal object (because you do a return in your constructor function) – potatopeelings Nov 24 '15 at 14:24
  • Ok, I think I get it. The property gets added when the method adds it to the object, kind of? Thanks for all the help and the examples, I might have to study up a bit on Object prototypes and constructors. :) – Jonas Eriksson Nov 24 '15 at 14:32
  • 1
    Yep, that's exactly what happens! http://speakingjs.com/ is a nice book if you're looking for something in depth. – potatopeelings Nov 24 '15 at 14:44