Raj
Raj

Reputation: 19

Angular Services and Scope - Why is value changing in other scope?

Need help understanding how the code below is working.

After the first load the value displayed in the div element as well as the input element is 'Username', as expected.

However, why does the value in the first div element get modified when i modify the value in the input element considering that both the controllers have different and mutually exclusive scope variables??.

I believe this is connect withed with the rootScope but i am not sure how to connect the dots.

<html ng-app='myApp'>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.js"></script>
    <script type="text/javascript">
        var app = angular.module('myApp', []);
        app.factory('userService',['$timeout', function($timeout){
            var user = {}
            
            $timeout(function(){
                
                user.name = 'Username';
            },5000);
           
            return user;
        }])
        app.controller('c1', ['$scope', 'userService', function($scope, userService){
            $scope.user = userService;
  
        }])
        app.controller('c2', ['$scope', 'userService', function($scope, userService){
            $scope.user = userService;
        }])
    </script>
    <body>
        <div ng-controller="c1"><h1>{{user.name}}</h1></div>
        <div ng-controller="c2"><input type="text" ng-model="user.name"/></div>
    </body>
    
</html>

Upvotes: 1

Views: 68

Answers (3)

Manish
Manish

Reputation: 5056

This is because you are referring the same factory object userService in both the controllers.

Your factory is a singleton object i.e its initialized only once. So when you inject this as a dependency to your controllers you actually are sharing the same instance with all the controllers across your app.

Your scope variable $scope.user is referring to the factory object in both your controllers. And you have binded user.name with ng-model.

So for the first time it displays Username as thats the value of $scope.user.name or rather i should say userService.name. So when the user types in the textbox this userService.name what is it actually binded to as $scope.user refers to userService and hence it updates the userService.name which is reflected in your controller c1 which is also referring to same instance of the factory object. And hence this behavior.

Below is a same demonstration that will help you understand more. As you can see i have created $scope.user as a new object in controller c1 so it wont refer to the factory object now and hence the name wont get updated. But in controller c2 it will be updated.

<html ng-app='myApp'>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.js"></script>
    <script type="text/javascript">
        var app = angular.module('myApp', []);
        app.factory('userService',['$timeout', function($timeout){
            var user = {}
            
            $timeout(function(){
                
                user.name = 'Username';
            },5000);
           
            return user;
        }])
        app.controller('c1', ['$scope', 'userService','$timeout', function($scope, userService,$timeout){
            $scope.user={};
             $timeout(function(){ 
                $scope.user.name = userService.name;
            },5000);
             
  
        }])
        app.controller('c2', ['$scope', 'userService', function($scope, userService){
            $scope.user = userService;
        }])
    </script>
    <body>
        <div ng-controller="c1"><h1>{{user.name}}</h1></div>
        <div ng-controller="c2"><input type="text" ng-model="user.name"/>
        <span>{{user.name}}</span>
        </div>
    </body>
    
</html>

Please read this for more info on services in angular

Official Documentation

Hope it helps :)

Upvotes: 1

cнŝdk
cнŝdk

Reputation: 32145

However, why does the value in the first div element get modified when i modify the value in the input element?

Because you are just using two way binding here, it's sure you have two differents controllers with two differents scopes but these two scope variables $scope.user refer to the same service value userService so a change in one controller will affect the second one.

In other words binding the two variables to the same service is the same as using one conroller.

That's how Data binding works in Angular:

Data-binding in AngularJS apps is the automatic synchronization of data between the model and view components. The way that AngularJS implements data-binding lets you treat the model as the single-source-of-truth in your application. The view is a projection of the model at all times. When the model changes, the view reflects the change, and vice versa.

Upvotes: 0

Deblaton Jean-Philippe
Deblaton Jean-Philippe

Reputation: 11388

In angularJS, services are singleton.

And as fas as you never update the reference of your user, you are always working with the same object.

This service shared by multiple components is a common way to share data.

Upvotes: 2

Related Questions