Why can't I use $rootScope instead of $scope?
Asked Answered
C

2

5

HTML file is this :

   <!DOCTYPE html>
<html lang="en" ng-app="myApp">

<head>
  <meta charset="utf-8">

  <title>HTTP Request</title>

  <script src="angularjs"></script>
  <script src="appjs"></script>

</head>
<body>
        <div ng-controller="myCtrl1">
            First Name: <input type="text" ng-model="fname" required>
            Last Name: <input type="text" ng-model="lname" required>
            <button ng-click="search()">Send HTTP Request</button>
            <p>Searching for : {{fname}} {{lname}}</p>
            <p>Response Status: </p>
            <p>{{status}}</p>
            <p>Data: {{data}}</p><br>
            <p>Total number of results : {{data.numResults}}</p>
        </div>
</body>
</html>

I have written a controller as :

var myApp = angular.module('myApp', []);

myApp.controller('myCtrl1', ['$rootScope', '$http', function($rootScope, $http) {
    $rootScope.fname = "";
    $rootScope.lname="";
    $rootScope.search = function() {

        var search_url = "/search?fname=" + $rootScope.fname + "&lname=" + $rootScope.lname;
        alert (search_url);
//      alert("/search?fname=" + $scope.fname + "&lname=" + $scope.lname);
        $http({method:'GET', url:search_url})
        .success(function(data, status, headers, config) {
            $rootScope.status = status;
            $rootScope.data = data;
            $rootScope.headers = headers;
            $rootScope.config = config;
        });
    };
}]);

But it shows url in alertbox as : /search?fname=&lname= But when I use $scope everywhere instead of $rootScope, it works fine (alert window shows url properly /search?fname=john&lname=player). Need help to understand $rootScope in details. Thanks.

Cabob answered 20/9, 2013 at 10:43 Comment(0)
W
9

You can use $rootScope instead $scope but your variable will be "global" and all controllers (if you have more then one) will see it.

But advantage of angular will be lost a bit. Because all models (a.e ng-model) will be created under specific $scope but not $rootScope

For each controller define private $scope.

so if you use two controllers in both you can define the variable name:

 $scope.data = "AAA";

and in other controller:

 $scope.data = "BBB";

they are different because refer to different instances (aka controllers)

about your problem:

you created this lines:

 First Name: <input type="text" ng-model="fname" required>
 Last Name: <input type="text" ng-model="lname" required> 

under controller myCtrl1. therefore it will not update your $rootScope but $scope that refers to myCtrl1.

I think you can use ng-change to notify $rootScope about change.

add to HTML:

 First Name: <input type="text" ng-model="fname" ng-change ="onfnameChange(fname)" required>
 Last Name: <input type="text" ng-model="lname" ng-change ="onlnameChange(lname)" required> 

to controller:

...
 $scope.onfnameChange = function(val){
   $rootScope.fname = val;
 };

$scope.onlnameChange = function(val){
  $rootScope.lname = val;
};
...

see Fiddle

Wentletrap answered 20/9, 2013 at 10:56 Comment(8)
Actually I have only two controllers and I am willing to have a $rootScope instead of using factory/service. But I am unable to use $rootScope as shown above. Do I need to do something with it, outside all the controllers, before using?Cabob
Okay. Now I understood. Thanks a lot Maxim for your help..! :)Cabob
The explanation is not correct. It is due to prototypal nature of scopes. Nothing to do with controllers except that they cause a new child scope to get created.Khrushchev
So every new controller will have its own scope which by default will be inherited from $rootScope?Cabob
@MaximShoustin See my fiddle that i derived from yours jsfiddle.net/qcUm6/1Khrushchev
@Khrushchev well, you defined list of inputs and set/get over name. better way then mine. I wanted just to show $rootScope/scope dependency. Glad to add you point , post your Fiddle in your answerWentletrap
@MaximShoustin i did add my fiddle :) It's not about the approach you suggested but the reason was not accurate. I suggest you also see the wiki link i have shared :)Khrushchev
This statement seems to have a glitch: "Because all models (a.e ng-model) will be created under specific $scope but not $rootScope". Isn't it the other way around ? If using the root scope and all variables then being global...Jennelljenner
K
9

Welcome to the world of prototypal inheritance.

You myCtrl1 scope inherits from $rootScope but any changes done on properties like string, integers and boolean on this scope would not affect the parent scope properties ($rootScope).

Basically you can access the properties of parent scope but you cannot change their reference (for object types). Any changes cause new properties being created on the child scope.

See my fiddle on how to handle it http://jsfiddle.net/qcUm6/1

Read this and all your doubts would be cleared https://github.com/angular/angular.js/wiki/Understanding-Scopes

Khrushchev answered 20/9, 2013 at 11:22 Comment(2)
That's a great link. This is something I wish I knew when I started with Angular. Would have saved me some horrible experiences with $parent.$parent.etc... :)Dekameter
@ErikHonn, this is a must read for everyone working on AngularJS, because we deal with scopes a lot :)Khrushchev

© 2022 - 2024 — McMap. All rights reserved.