0

This is a line of code from Template 1 (the template displays a list of users). The controller for this is MainCtrl.

<div class="modal fade" id="myModal" tabindex="-1" role="dialog" ng-controller="MainCtrl">

<a data-toggle="modal" data-target="#configureUserModal" href="#" ng-click="getUserDetails(user.id)">{{user.name}}</a>

</div>

<modal-configure-user></modal-configure-user>

The relevant code in my MainCtrl is:

angular.module('app')
.controller('MainCtrl', ['$scope', '$http', '$window', '$rootScope', '$routeParams', '$timeout', function(
    $scope, $http, $window, $rootScope, $routeParams, $timeout) {

$scope.getUserDetails = function (userId) {
        $http.get("/user/" + userId).success(function(data) {
            $scope.userData=data[0];
            console.log($scope.userData.name); //Line 1
        });
};

}]);

Now Template 2 for individual users opens when the User Name in Template 1 is clicked. I just want to display the user name in Template 2, so I do:

<div class="modal fade" id="configureUserModal" tabindex="-1" role="dialog" ng-controller="MainCtrl">

{{userData.name}} //Line 2

</div>

The controller for Template 2 is also MainCtrl. But the problem is Line 1 works (prints the user name to console), Line 2 doesn't (it just shows up as null). I can't seem to figure out what the problem is. Is it a timing issue? Is Template 2 loaded faster than the HTTP request?

geekchic
  • 2,371
  • 4
  • 29
  • 41

1 Answers1

1

Each ng-controller declaration will get its own instance of the controller, and $scope as well. Changing the data on the scope for one ng-controller, will not impact the other.

If you want to share data, you should be using Angular services. I am going to demonstrate how to use an Angular factory to share data, but you can just as easily implement a service too.

For the differences between a service vs factory, see here.

Angular services and factories are singletons, which means that the same instance is used everywhere that they are injected. This makes it perfect for sharing data.

Here is how you could share data using a factory:

var app = angular.module('app', []);
app.factory('userDetailService', function($http) {    
    var userData = {};
    function getUserDetails(userId) {
       return $http.get("/user/" + userId).success(function(data) {
           // copy is used to preserve the reference
           angular.copy(data[0], userData);
           console.log(userData.name);
        });
    }
    return {
        userData: userData,
        getUserDetails: getUserDetails
    }

});

Then you can call the userDetailService, and bind to userData in any of your controllers. Call getUserDetails() whenever you need to and all bindings to userData will automatically be updated.

// controller 1
app.controller('controller1', function($scope, userDetailService) {
    $scope.userData = userDetailService.userData;
    userDetailService.getUserDetails('johnsmith').success(function() {
          // success - do anything else here if you want
    });
});


// controller 2
app.controller('controller2', function($scope, userDetailService) {
    $scope.userData = userDetailService.userData;
});

HTML

<div ng-controller="controller1">
     {{userData.name}}
</div>

<div ng-controller="controller2">
     {{userData.name}}
</div>
Community
  • 1
  • 1
Michael Kang
  • 52,003
  • 16
  • 103
  • 135