Wednesday, 31 December 2014

Tree structure present in XAML

In this post we can see XAML. XAML is an XML based mark up language. For specifying the settings and characteristics of a class. It is concentration mainly in the UI presentation and some part of animation along with binding.

C# is used for control the flow of XAML and specifying the Behavior of XAML tag.It consists of two kind of Trees to represent the elements. First is Logical Tree and Visual Tree.

Logical Tree means comprises the elements as they listed in the XAML.

Visual Tree means includes the parts of all things that is used to visualize the control and parts like border of a control , presenter


For Example Let we take the below syntak.

<Window x:Class="WpfApplication3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <Button>Click Me</Button>
    </StackPanel>
</Window>



From the XAML Code now we are going to define the Logical tree and visual tree.

Logical Tree: Specifies only the element present in the XAML

              Window 
                    |
            StackPanel
                    |
               Button


Visual Tree: Includes all things which are useful in display the controls.

             Window 
                    |
               Border
                   |
       AdornerDecorter
                    |
       ContentPresenter
                    |
            StackPanel
                    |
               Button
                    |
            ContentPresenter

From the above you can learn some basic things about Tree structure present in XAML.
             

Thursday, 25 December 2014

Call a method in parent controller from the child controller in Angular

In this post we are going to see how to call a method which is present in the parent controller from the child controller.

HTML:
*******

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <link href="css/bootstrap.min.css" rel="stylesheet">
    <title></title>
</head>
<body data-ng-app="locapp">

    <div ng-controller="parentController" class="well">
        <ul>
            <li ng-repeat="dt in data">{{dt}}</li>
        </ul>
        <div class="btn btn-info" ng-click="getData()">Call Child Controller Method</div>

        <div class="btn btn-info" ng-click="getStudent()">Call Sibling Controller   Method</div>
        <div ng-controller="childController">
            <ul>
                <li class="well-sm" ng-repeat="emp in employees">{{emp}}</li>
                <br/>
                <div class="btn btn-info" ng-click="getParentInfo()">Call Parent Controller Method</div>
            </ul>
        </div>
    </div>

    <div ng-controller="siblingController">
        <ul class="panel">
            <li class="well-sm" ng-repeat="stud in students">{{stud}}</li>
        </ul>
    </div>

<script type="application/javascript" src="js/jquery-2.0.0.min.js"></script>
<script type="application/javascript" src="js/bootstrap.min.js"></script>
<script type="application/javascript" src="js/angular.js"></script>
<script type="application/javascript" src="ang/issue.js"></script>

</body>

</html>

Js:
*****

From the Controller side


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

locapp.controller('parentController', function ($scope, $rootScope) {
    var i = 0;
    $scope.data = [];

    $scope.getData = function () {
        i++;
        $scope.$broadcast('getEmployees', ['Name ' + i, 'ABCDG' + i]);
    };

    $scope.getStudent = function () {
        $rootScope.$broadcast('getStudents', ['Rajesh', 'Suresh']);
    };

    $scope.$on('runData', function (evt, datas) {
        $scope.data = datas;
    })

});

locapp.controller('childController', function ($scope, $rootScope) {
    $scope.employees = [];

    $scope.$on('getEmployees', function (evt, data) {
        angular.forEach(data, function (item) {
            $scope.employees.push(item)
        });
    });

    $scope.getParentInfo = function () {
        $scope.$emit('runData', ['1', '2']);
    };


});

above code cleanly explains the that from the child controller we are calling a method getParentInfo inside that method we are emit a method from child controller to parent controller along with the data. because of emit the parent controller assign a value 1,2 in the array variable data.

Output:
******




From the above code you can learn how to call a method from the child controller to parent controller.

Broadcast a Method to child controller method and silibling controller method in angular js

In this post we are going to see how to call the method which is present inside a another controller, In that it is separate in to two ways downwards and upwards from the controller.$broadcast a method means we are calling a method downwards from the mention scope, if the corresponding method is found then the method present in any controller can be executed, we can pass the data also in broadcast.

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

locapp.controller('parentController', function ($scope, $rootScope) {
    var i = 0;
    $scope.getData = function () {
        i++;
        $scope.$broadcast('getEmployees', ['Name ' + i, 'ABCDG' + i]);
    };

    $scope.getStudent = function () {
        $rootScope.$broadcast('getStudents', ['Rajesh', 'Suresh']);
    }


});


HTML:
********

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <link href="css/bootstrap.min.css" rel="stylesheet">
    <title></title>
</head>
<body data-ng-app="locapp">

    <div ng-controller="parentController" class="well">
        <div class="btn btn-info" ng-click="getData()">Call Child Controller Method</div>
        <div class="btn btn-info" ng-click="getStudent()">Call Sibling Controller                                Method</div>
        <div ng-controller="childController">
            <ul>
                <li class="well-sm" ng-repeat="emp in employees">{{emp}}</li>
            </ul>
        </div>
    </div>

    <div ng-controller="siblingController">
        <ul class="panel">
            <li class="well-sm" ng-repeat="stud in students">{{stud}}</li>
        </ul>
    </div>

<script type="application/javascript" src="js/jquery-2.0.0.min.js"></script>
<script type="application/javascript" src="js/bootstrap.min.js"></script>
<script type="application/javascript" src="js/angular.js"></script>
<script type="application/javascript" src="ang/issue.js"></script>

</body>
</html>



1.  $broadcast a method from parent controller to the child controller using scope.

Why normally we are using the scope in this broadcast, because we are going to call a controller which present as child controller for current controller. so we are setting the place from where to broadcast and which is the shortest one to reach soon., even we can broadcast from the rootScope also. it will broadcast the data.

locapp.controller('childController', function ($scope, $rootScope) {
    $scope.employees = [];

    $scope.$on('getEmployees', function (evt, data) {
        angular.forEach(data, function (item) {
            $scope.employees.push(item)
        });
    });

});


Now the childController is present inside the parentController, so we are broadcast a method getEmployees from the Parent controller along with data from the method getData in parentController. In childController we are having the getEmployees method in $on, the call back have a first argument which is event, second argument is a data supplied from the $broadcast.Here we are using the $scope to $broadcast because the method is present inside a child controller or inside the same scope there is another scope.

Output:



2. $broadcast a method from controller to sibling controller or any controller using the $rootScope.

Normally if we want a method to call from another controller which is not present inside our controller, may be present as sibling or present in some where hierarchy, To call a method which is present somewhere else, then we can broadcast a method from the rootScope


locapp.controller('siblingController', function ($scope, $rootScope) {

    $scope.students = [];

    $scope.$on('getStudents', function (evt, data) {
        angular.forEach(data, function (item) {
            $scope.students.push(item);
        })
    })

});


Here we are broadcast a method from the $rootScope because the controller is somewhere else.

Output:





From the above post you can learn how to broadcast the method from another controller.




$rootScope:infdig 10 $digest() iterations reached. Aborting! Watchers fired in the last 5 iterations combination of (Angular js and IE) Bug

In this post we are going to see a concept of infinite digest, that is takes place in the angular js. probably when you see the angular js website they mention it as this kind of error is raised in only two kind of scenario's. i.e is mentioned like below.

        According to the angular js support portal, they mention this kind of error is raised when application model becomes unstable. and each life cycle triggers a state change and subsequent $digest will happen, so to avoid this kind of infinite digest loop, they make a count of 10 after that they stop the digest iteration, and throws the error.Now let we see what are the two scenario's that can happen, i.e mention by them.

Scenario 1 :

Watching a variable change and doing a operation for that change or executing a function for a change, for every execution $digest will execute, But if you certainly change the value of variable which is watched by the same trigger, it will again fires the watch of that variable, so now the $digest is fires endless.In this scenario they will raise a Error like 10 $digest iteration reached.

$scope.$watch('count',function(){
      $scope.count = $scope + 1;        // digest will run for execute a function
});

Scenario 2:

Another scenario is there which will comes in the ng-repeat directive execution, how in this we are getting the $digest iteration, simple instead of give the collection variable in the loop, we are giving a function in ng-repeat which will return a array, so for every execution nr-repeat gets the first value only, so repeatedly we are doing the same process.

<div ng-repeat="emp in getemp()"
{{emp}}
</div>

$scope.getemp = function(){
 return ['suresh','ramesh','ramu'];
};

so we analysis the error causing scenario's now we are going to actually another scenario also causing this same error, actually this is a Bug of angular due to IE.

When we are design a application with angular, we have to keep in mind that every error raised in the angular could be because of angular itself there is a side effects of others things also, like browser, jquery. 


when you are working with 5000 to 6000 lines of angular code that time if you got a error like 

[$rootScope:infdig] 10 $digest() iterations reached. Aborting!

Watchers fired in the last 5 iterations

then the first thing that goes in our mind that we made mistake some we where else, which meets the one of the above two scenario's, so you will actually got stuck in to the every line by line code to find out that loop hole. finally it takes a lot of efforts a day or more than day to find out the root cause which is actually causing this problem.Instead of doing this first find out whether this is really our problem or angular problem. because In Angular there is a Bug which is cause in IE  predominately  below version IE 11, and also in some of the other browsers in older version of angular.

First we see the scenario.

Develop a  application which use the angular js version 1.2.16, then made a code which have a tag with href="#" and along with ngclick which have the functionlity of adding a value for some collection, and that collection is mentioned in a ng-repeat.

Now for this scenario, this works fine and very well for all Browsers other the IE version less than 11

what kind of error will come for IE version less than 11 ?
 you will get a error like


[$rootScope:infdig] 10 $digest() iterations reached. Aborting!

Watchers fired in the last 5 iterations: [["fn: $locationWatch; newVal: 19; oldVal: 18"],["fn: $locationWatch; newVal: 20; oldVal: 19"],["fn: $locationWatch; newVal: 21; oldVal: 20"],["fn: $locationWatch; newVal: 22; oldVal: 21"],["fn: $locationWatch; newVal: 23; oldVal: 22"]],

In the above error code it tells that it is get raise from the $locationWatch, you may wonder why this error is raising , so you have starts to check for all Watch which is goes wrong, but the issue is not in your code, it is because of placing a code Href="#" in the a tag, This Href makes a location changes , so why the error raises. now we see inside the angular js code.


    // update browser
    var changeCounter = 0;
    $rootScope.$watch(function $locationWatch() {
      var oldUrl = $browser.url();
      var currentReplace = $location.$$replace;

      if (!changeCounter || oldUrl != $location.absUrl()) {
        changeCounter++;
        $rootScope.$evalAsync(function() {
          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).
              defaultPrevented) {
            $location.$$parse(oldUrl);
          } else {
            $browser.url($location.absUrl(), currentReplace);
            afterLocationChange(oldUrl);
          }
        });
      }
      $location.$$replace = false;

      return changeCounter;

    });

In the above code in angular js, we can see the changeCounter. will keep on increasing this is because that the # tag mention in the a tag.that makes the $locationWatch to fire

If there are hyperlinks in your App, make sure you handle them properly, and they are doing what you want them to do, because, "href", can cause location change, which your application might not like

If there is no need for HTML5 mode in your app then following code will resolve this issue

    locapp.config(function ($locationProvider) {
        $locationProvider.html5Mode(false).hashPrefix('!');

    });

but if HTML5 mode is needed then do the following

so place href="javascript:void(0);", this will stop the location change and infinite loop stops executes, even after change the code still the $infdigest get then place the Latest Angular version 1.2.28, it is fixed, especially  this issue occurs only in the IE not in the other browsers.


Sometimes it occurs in chrome browsers itself, you can simulate that using the following code, by placing the pushstate in chrome.

javascript:
**********

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

    locapp.controller('locController', function ($scope, $rootScope) {
        $scope.setLoc = function () {
            history.pushState(null, '', '/index');
            angular.element(document.body).scope().$apply();
        }

    });


HTML:
**********


<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body data-ng-app="locapp">

<script id="inc.html" type="text/ng-template">
    <button  ng-click="setLoc()">Set Location</button>
</script>

    <div ng-controller="locController">
        <div ng-include="'inc.html'"></div>
    </div>

<script type="application/javascript" src="js/jquery-2.0.0.min.js"></script>
<script type="application/javascript" src="js/bootstrap.min.js"></script>
<script type="application/javascript" src="js/angular.js"></script>
<script type="application/javascript" src="ang/issue.js"></script>

</body>

</html>


so from the code you can see that the location keep on change result in $infdigest issue in chrome browser itself.


So i think this post may resolve and give a better idea about the $infdigest issue in angualr js.