@Cybrilla » Blog Archives

Tag Archives: AngularJS

Uncategorized

Angular Digest Cycle

Published by:

I am going to explore the Angular digest cycle, which is the process behind Angular data binding. By the end of this post, you’ll understand how data binding works in angular, what is digest cycle, how we trigger digest cycle by calling $scope.$apply() and how exactly digest cycle works.

First of all, let me tell you one thing about Javascript .i.e
Javascript Is Turn Based.
The JavaScript code we write doesn’t all run in one go, instead it executes in turns. Each of these turns runs uninterrupted from start to finish, and when a turn is running, nothing else happens in our browser.
Instead, whenever there is a task that takes some amount of time, such as an Ajax request, waiting for a click event, or setting a timeout, we set up a callback function and finish our current turn. Later, when the Ajax request completes, a click is detected, or the timer completes, a new JavaScript turn is created and the callback is run to completion.

Let’s look at the below code

When the JavaScript code is loaded, that is a single turn. It finds a button, adds a click listener, and sets a timeout. Then the turn is complete, and the browser will update the web page if necessary, and begin accepting user input.

If the browser detects a click on #clickMe, it creates a new turn, which executes the buttonClicked function. When that function returns, that turn is complete.
Now take a look at a very simple AngularJS snippet where you start typing your name into an input field. There is also a div that shows what you typed, in real time:

Whenever the name model changes, the expression automatically updates itself. It’s done just by setting up a watcher on the name model.

Most watchExpressions are created implicitly within AngularJS, but you can also create them manually. Let me show you how to do that:

Note : Here in watch expression we pass newValue and oldValue. When watch expression changes, then the listener function is called. This is also known as dirty checking.

For this strategy to work, we need to know when data has possibly changed, and this is where $scope.$apply comes into play.

The step that checks to see if any binding values have changed actually has a method, $scope.$digest(). But we almost never call it directly, instead we use $scope.$apply() which will call $scope.$digest() for you.

$scope.$apply() takes a function or an Angular expression string, and executes it, then calls $scope.$digest() to update any bindings or watchers.You can also say that it just  starts new javascript turn. Digest cycle executes at least twice.

So, when do you need to call $apply()? Very rarely, actually. AngularJS actually calls almost all of your code within an $apply call. Events like ng-click, controller initialization, $http callbacks are all wrapped in $scope.$apply(). So you don’t need to call it yourself, in fact you can’t. Calling $apply inside $apply will throw an error.

So what happens when we write

1. The directive ng-model registers a keydown listener with the input field. When the input field text changes a keydown event is fired and the corresponding listener is called to handle it.

2. Inside the keydown listener the directive assigns the new value of input field to the scope model specified in ng-model. In our case the model name is updated with the new value. This code is wrapped inside $apply() call.

3. After $apply() ends the digest cycle starts in which the watchers are called. If you have an expression {{name}} in the view it has already set up a watcher on scope model name. So, in digest cycle this watcher gets called and the listener function executes with the newValue and oldValue as arguments. The job of this listener is to update the DOM with the newValue probably using innerHTML.

4. The overall result is that you see the {{name}} updated with whatever you type into the input field instantly.
References:

http://www.thinkful.com/projects/understanding-the-digest-cycle-528/

Notes On AngularJS Scope Life-Cycle

 

Javascript ProgrammingTips

Execute a function within a Directive from outside in AngularJS

Published by:

We were working on two problem statements at different points in time of a project and we interestingly found similar solution for both.

Problem A: We have a form, one of the input fields  (defined as a directive) has a clear button. This clears the text in the input field, the data in the ng-model as well as the data held in the variable that gets submitted finally via the form. Now, we have a universal clear button that also needs to clear all the 3 data points.

Problem B: We have a section that has been defined as a directive which can be expanded/collapsed using a toggle button. The expand/collapse is handled by the directive. The initial state of the directive, whether it should be expanded or collapsed, is actually dependent on a value obtained from an API call.

In both cases the common thing that one can notice is that there is an external trigger that needs to be passed on into the directive. In Angular 1.4 there is no direct way to do this. Directives do support two way binding, and passing initial values. But neither would solve the exact requirement in both problems.

The solution that we came up with was passing a control object to the directive. The controller defined a control object, a key of which will be pointing to a function. This object was passed on to the directive, and directive initialised the control object’s key (control object which is two-way bound) with a function that gives access to the variables/functions inside the directive. Being two-way bound, this function is now available in the controller. This can be passed on to anywhere (factory, as it was in case of solution for problem B) or used locally.

Sample code: