Try it

Uhm, no matter how many times I click on the login button, nothing happens. That is weird… $scope.loggedIn is equal to the service’s loggedIn but when I update the service with the buttons I get no updates.

The problem doesn’t lie in Angular, this is a common misunderstanding of how Javascript works.

This is how some people think this is working:

But what is really happening is this:

Why is this happening? Let’s see an example:

1234

vara=10;varb=a;a=20;console.log(b);// 10

What has happened here? We created two variables, a with the value of 10 and b. We assign the value of a to bnot a reference, so what b has is a copy of the value of a. Then if we assign a different value to a, b won’t change because what b contains is a primitive with the value of 10.

So when we did:

1

$scope.loggedIn=Auth.loggedIn;

What we did was just copying the value of Auth.loggedIn, aka false, to $scope.loggedIn, so if the Auth service updates, and with our current implementation, we won’t notice it.

We assigned a reference of our Auth service (which is an object) into $scope.auth and since it is a reference and not a value we can modify our Auth service without the fear of having a $scope.auth with “outdated” data.

Try it

Now it works! And in my humble opinion, it makes more sense to have a reference to the service just once instead of having your service replicated again in the controller.

Here we see how MainCtrl consumes the service and loggedIn has a reference to the Auth service.

Having this in mind, this is just one way to consume your services. You may like it, or maybe not. That is not a problem because Angular is not opinionated in these things, so depending on your use case, you could need to consume it in different ways.

One of the drawbacks of this way is that you’re giving the view knowledge about your service. That can be non desired in certain cases. On the other hand, you would need to do some things in the controller when you login or logout. In both cases, you could rewrite your code like this:

auth.js

123456789101112131415

app.service('Auth',function(){varloggedIn=false;// this is privatereturn{login:function(){loggedIn=true;},logout:function(){loggedIn=false;},isAuthenticated:function(){returnloggedIn;}};});

mainctrl.js

123456789

app.controller('MainCtrl',function($scope,Auth){$scope.isAuth=Auth.isAuthenticated;$scope.login=function(){// Do things before loginAuth.login();// Do extra things after login};$scope.logout=Auth.logout;// No need for extra things});

As you can see, we can assign to our scope the functions we have in the service as we did with isAuth and logout or create a function that will do extra things plus the call to the login method of the service.

Even when this is a matter of personal design decisions, I think that there are use cases for both solutions.

And last but not least, I want to thank PigDude because it was he who gave the solution with awesome examples and explanations, as well as all the users of Hacker news who were kind to point some issues that had to be fixed. Having said this, I highly recommend all of you to join us in #angularjs at Freenode. And remember, the blog is on github so you can send your pull requests :).