Showing posts with label $rootScope. Show all posts
Showing posts with label $rootScope. Show all posts

Sunday, June 15, 2014

ng:repeat and radio button problems

We all know ng-repeat creates it's own scope for each repeated item. Take the following example

<html>
<head>
  <script data-require="angular.js@*" data-semver="1.3.0-beta.5" src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
  <script>
    angular.module("sampleapp", []).controller('samplecontroller', function($scope) {
      $scope.nameList = [{
        name: "Lemon"
      }, {
        name: "John"
      }];

    });
  </script>

</head>

<body ng-app="sampleapp" ng-controller="samplecontroller">
  <div ng-repeat="item in nameList">{{item.name}}</div>
</body>
</html>



The above code actually creates two divs (one for each item in the nameList) and renders those with the content and the output would be
Lemon
John

If we try to do similar thing where we put radio buttons instead of divs it will create separate scope for each radio button.

Let's change our HTML to the below one:


<!DOCTYPE html>
<html>

<head>
  <script data-require="angular.js@*" data-semver="1.3.0-beta.5" src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
  <script>
    angular.module("sampleapp", []).controller('samplecontroller', function($scope) {
      $scope.nameList = [{
        name: "Lemon"
      }, {
        name: "John"
      }];
      $scope.selectedItem = $scope.nameList[0];
    });
  </script>

</head>

<body ng-app="sampleapp" ng-controller="samplecontroller">
  <form>
    Select a name fom two names:
    <br/>
    <span ng-repeat="item in nameList">
    <input type="radio" name="name" ng-value="item" ng-model="selectedItem">{{item.name}}<br/>
  </span>
    <br/>The selected name:{{selectedItem.name}}
  </form>

</body>

</html>

Here is the Plunkr link:

Plunkr for above HTML

However if we select any radio button it does not change the selectedItem value of the scope, because it changes value of selectedItem of the new scope for span, to bind to the parent scope's selectedItem object we have to change the code to....

<!DOCTYPE html>
<html>

<head>
  <script data-require="angular.js@*" data-semver="1.3.0-beta.5" src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
  <script>
    angular.module("sampleapp", []).controller('samplecontroller', function($scope) {
      $scope.nameList = [{
        name: "Lemon"
      }, {
        name: "John"
      }];
      $scope.selectedItem = $scope.nameList[0];
    });
  </script>

</head>

<body ng-app="sampleapp" ng-controller="samplecontroller">
  <form>
    Select a name fom two names:
    <br/>
    <span ng-repeat="item in nameList">
    <input type="radio" name="name" ng-value="item" ng-model="$parent.selectedItem">{{item.name}}<br/>
  </span>
    <br/>The selected name:{{selectedItem.name}}
  </form>

</body>

</html>


The $parent refers to the parent scope so now we refer to the selectedItem object which is defined in our controller.

The above approach looks simple, however when the radio button goes under a transcluded directive  we need to refer something like $parent.$parent....... till we reach the main controller's scope.

Another approach would be doing this in event publish/subscribe pattern.
Here is the implementation:


<!DOCTYPE html>
<html>

<head>
  <script data-require="angular.js@*" data-semver="1.3.0-beta.5" src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
  <script>
    angular.module("sampleapp", []).controller('samplecontroller', function($scope, $rootScope) {
      $scope.nameList = [{
        name: "Lemon"
      }, {
        name: "John"
      }];
      $scope.selectedItem = $scope.nameList[0];

      $scope.changehappened = function(data) {

        $rootScope.$emit('nameselected', data);
      };
      $rootScope.$on('nameselected', function(evt, data) {

        $scope.selectedItem = data;
      });
    });
  </script>

</head>

<body ng-app="sampleapp" ng-controller="samplecontroller">
  <form>
    Select a name fom two names:
    <br/>
    <span ng-repeat="item in nameList">
    <input type="radio" name="name" ng-value="item" ng-model="$parent.s" ng-change="$parent.changehappened(item)">{{item.name}}<br/>
  </span>
    <br/>The selected name:{{selectedItem.name}}
  </form>

</body>

</html>



Sunday, December 15, 2013

Example of Scope hierarchy in Angular JS

Angular JS has a $scope object which is mostly used to expose the domain model, model or domain level properties are assigned to $scope and can be accessed in view as well as controller.

In a single application we can have multiple controllers and each controller can refer to their own instance of $scope object, parent scope as well as $rootScope which is parent most scope of an application.$rootScope is created when the application bootstraps.

In the below example I have 2 controllers for my application, one is mainController and other one is named as subController. subController has a child controller named as childController.

MainController has one property named as Mngname, and it assigns a property named compayName  to it's parent scope which is nothing but $rootscope.

SubController has one property named as amName.

ChildController takes $rootScope along with $scope as it's inputs, it has one property named empName, it creates and assigns  one property of it's parent scope i:e, scope of SubController named as dept. It creates another property comp which holds the value of companyName property of $rootScope.


<!DOCTYPE html>
<html>
<head> <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/
angular.js"></script>
    <script>
        var  mainController=function($scope)
        {
            $scope.MngName='Jade';
            $scope.$parent.companyName='Mcommerce';
        }
        var  subController=function($scope)
        {
            $scope.amName='Jane';
            $scope.childController=function($scope,$rootScope)
            {
                $scope.empName='Scott';
                $scope.$parent.dept='Sales';
                $scope.comp=$rootScope.companyName;

            }

        }
         var appVar=angular.module('ScopeTest',[]);
    </script>
    <title>Angular scope chain</title>
</head>
<body ng-app="ScopeTest">
   <div ng-controller="mainController">
        <table title="ParentTable" border="5px">
            <caption>Level1</caption>
            <tr>
                <td>Manager Name</td>
            <td>{{MngName}}</td>
            </tr>
            <tr>
                <td>
            <table border="4px" ng-controller="subController">
                <caption>Level2</caption>
                <tr>
                <td>Associate Manager Name</td>
                   <td>{{amName}}</td>
                </tr>
                <tr>
                    <td>Reporting To</td>
                    <td>{{MngName}}</td>
                    </tr>
                <tr>
                    <td>Department Assigned at Employee Level</td>
                    <td>{{dept}}</td>
                </tr>
                <tr>

                    <td>

                        <table border="3px" ng-controller="childController">
                            <caption>Level3</caption>
                            <tr>
                                <td>Employee Name</td>
                                <td>{{empName}}</td>
                            </tr>
                            <tr>
                                <td>Comp</td>
                                <td>{{comp}}</td>
                            </tr>


                        </table>
                    </td>
                </tr>
            </table>
                </td>
            </tr>
        </table>

   </div>

</body>
</html>