0

I am a newbie to AngularJS and while learning it I came across a wonderful post about how scopes are nested and inherited in HTML markup: Understanding Scopes

Also I went through this Plunker to understand what the above post is saying.

I have created this JSFiddle to understand the above concepts.

HTML:

<body ng-app="myApp">
    <h1>Hello AngularJS!</h1>
    <div ng-controller="myCtrl">{{hello}}
        <div anchor-link> 
            <a href="javascript:;">click me</a>
            <div ng-show="t.show">show me</div>
            <div ng-hide="t.show">hide me</div>
        </div>
    </div>
</body>

JS:

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

app.controller('myCtrl', function ($scope) {
    $scope.hello = 'Hello World!';
    $scope.t = {
        show: true
    };
});

app.directive('anchorLink', function () {
    return {
        restrict: 'EA',
        link: function (scope, elem, attr) {
            elem.on('click', function () {
                 scope.t.show = !scope.t.show;
            });
        }
    };
});

Now my question:

  1. Why doesn't two-way data binding work in my fiddle? Isn't the scope from my custom directive supposed to inherit from its parent (i.e. controller)?

  2. If I am using $scope.t as an object on controller scope. then why doesn't it toggle "show me" and "hide me" divs? I also tried using scope: true in my custom directive, but it still doesn't work.

  3. Is it because scope in my link function doesn't inherit prototypically?

  4. Is it really changing parent scope's $scope.t object?

1 Answer 1

2

So what you need to do is this:

http://jsfiddle.net/DkFx9/

What is going on here is that you are using jQuery's click event handler to handle the click event and changing the scope variable in the handler. The problem with this is that there is no way for angular to know that something in scope changed and hence it needs to update the views.

Typically, when you do something similar using angular's directive like ng-click="t.show = !t.show", then angular knows that some even occurred through angular and it runs the digest loop to do dirty checking and update the related views.

In your case, we have to tell angular that something is happening and it must run the digest loop. scope.$apply takes the piece of code you want to execute and then asks angular to run the digest loop and update the views that need to be updated.

Hope that helps.

Sign up to request clarification or add additional context in comments.

4 Comments

Oh!! Ok. But is there any other way than using $apply? And What about my 4th question. Even though data binding is not happening for reasons explained by you ..is the value actually changing in the parent scope or not? I guess yes as alerts do show updated value in event handler
Also can I make the scope isolate so that binding occurs? or it will not affect for the same reasons you explained?
So run the JSfiddle I shared. And you will notice that the values are changing indeed. The values are changing, yes. And data binding is happening. The only issue was that Javascript object gets changed but Angular does not know about it so it can't update the views and do the DOM manipulation as required by ng-hide and ng-show. So basically, the controller's scope's t object has the new changed value but the value was not reflected in the view because of digest loop not running.
If you isolate the scope, then nothing will be reflected outside i.e. in the controller's scope (because the directive now has an isolated scope).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.