12

I know there are other similar questions on how to pass data between Angular controllers.

What I wonder is how to deal with this in a view..

Lets say I have a UserController for login, registration etc. And an AppController for the actual app functionallity .

The UserController would be fairly easy, its sort of standalone from the rest. But what if the app needs to know about stuff from the user controller?

Lets say the app view needs to hide/show stuff depending on if the user is logged in or not. Or it could be if the user is male or female etc.

Should the app model keep its own copy of the user model state? e.g. appModel.isLoggedIn , appModel.gender etc ?

feels a bit redundant, but at the same time more testable.

So what is the correct way to do this?

Roger Johansson
  • 22,764
  • 18
  • 97
  • 193

2 Answers2

19

Short answer

Create a service, see Creating Services for details.

Long answer

Services are - per se - application-wide singletons, hence they are perfect for keeping state across views, controllers & co.:

app.factory('myService', [ function () {
  'use strict';
  return {
    // Your service implementation goes here ...
  };
}]);

Once you have written and registered your service, you can require it in your controllers using AngularJS' dependency injection feature:

app.controller('myController', [ 'myService', '$scope',
  function (myService, $scope) {
  'use strict';
  // Your controller implementation goes here ...
}]);

Now, inside your controller you have the myService variable which contains the single instance of the service. There you can have a property isLoggedIn that represents whether your user is logged in or not.

Community
  • 1
  • 1
Golo Roden
  • 140,679
  • 96
  • 298
  • 425
  • So, if I have an UserService, which contains userid, isLoggedIn properties.. and share this object between my controllers.. can I bind directly to it in the views? eg. {{userState.Username}} ? will changes in the service state be tracked the same way as the model is? – Roger Johansson Jul 04 '13 at 13:30
  • 1
    Have a look at [AngularJS: How to watch service variables](http://stackoverflow.com/questions/12576798/angularjs-how-to-watch-service-variables), this should answer your question. – Golo Roden Jul 04 '13 at 13:32
2

To further specify the answer @GoloRoden gave, this is an example of how you can share state values across all controllers taking the service as a dependency.

App.factory('formState', formState);

function formState() {        

    var state = {};

    var builder = "nope";
    var search = "nope";

    state.builder = function () {
        return builder;
    };

    state.search = function () {
        return search;
    };

    state.set = {
        'builder': function (val) {
            builder = val;
        },
        'search': function (val) {
            search = val;
        }
    };

    return {
        getStateManager: function () {
            return state;
        }
    };
}

App.controller('builderCtrl', builderCtrl);

builderCtrl.$inject = ['formState']
function builderCtrl(formState) {
    var stateManager = formState.getStateManager();

    activate();

    function activate() {
        console.log("setting val in builder");
        stateManager.set.search("yeah, builder!");

        console.log("reading search in builder: " + stateManager.search());
        console.log("reading builder in builder: " + stateManager.builder());
    }
}

App.controller('searchCtrl', searchCtrl);

searchCtrl.$inject = ['formState']
function searchCtrl(formState) {
    var stateManager = formState.getStateManager();

    activate();

    function activate() {
        console.log("setting val in search");
        stateManager.set.search("yeah, search!");

        console.log("reading search in search: " + stateManager.search());
        console.log("reading builder in search: " + stateManager.builder());
    }
}
pluralMonad
  • 313
  • 1
  • 2
  • 7