0

I want to access Scope variable total in directive link property.

Even though total value is updating on mouseDown event was fired, but the $scope.total was not changing.

Here is the code

functionality: Total amount changes when mouse down on respective boxes

 var app = angular.module("billModule", []);
        app.controller("billController", function ($scope) {
            $scope.total = 0.0;
        });
        app.directive("menu", function ($document) {
            return {
                restrict: "EA",
                replace: true,
                link: function (scope, element, attr) {
                    element.on("mousedown", function () {
                        scope.total += Number(attr.cost);
                      //console.log("total is "+ scope.total);
                    });
                },
                template: function (element, attr) {

                    return "<div class='box' title='$" + attr.cost + "'>" + attr.item + "</div>";
                }
            }
        })
.box {
            width: 132px;height: 38px;background-color: red;cursor: pointer;border: groove;text-align: center;padding-top: 5px;font-size: 33px;color: white;
        }
            .box:hover {
                /*background-color: blue;*/
                border: inset;
            }
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="billModule">
        <div ng-controller="billController">
            <menu item="Gold" cost="20"></menu>
            <menu item="fruits" cost="40"></menu>
            <menu item="phone" cost="90"></menu>
            <menu item="water" cost="50"></menu>
            <menu item="monitor" cost="70"></menu>
            <div>{{total | currency : '$':2}}</div>
        </div>

    </div>

1
  • add scope.$apply(); after you have console in link in the directive Commented Oct 27, 2016 at 12:26

2 Answers 2

2

Angular is not aware of the change, since it was made using an external event handler, and not an angular event handler (ngClick for example). To make angular aware of the change, wrap it with scope.$apply:

scope.$apply(function() {
    scope.total += Number(attr.cost);
});

If you're using angular 1.3 or above, use scope.$applyAsync, as it's a bit more performant.

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

4 Comments

when we are accessing scope outside do we have to use $apply?
When we are changing a scope property we need to notify angular about it, so it can start the digest cycle, and react to the changes. To do so, we use $apply.
but we are not using $apply in controller(), why?
If you use angular methods or event handlers, such as $http or ngClick, they use $apply internally to start the digest loop. If you'll use a element.on in the controller without $apply, you'll have the same problem.
0

Use 'scope.$digest();' after 'scope.total += Number(attr.cost);' your total will gets updated in the template. Refer below plnkr

http://plnkr.co/edit/nOPggwreTTEukYUMbD1X?p=preview

Code:

var app = angular.module("billModule", []);
app.controller("billController", function ($scope) {
    $scope.total = 0.0;
});
app.directive("menu", function ($document) {
    return {
        restrict: "EA",
        replace: true,
        link: function (scope, element, attr) {
            element.on("mousedown", function () {
                scope.total += Number(attr.cost);
                scope.$digest();
              //console.log("total is "+ scope.total);
            });
        },
        template: function (element, attr) {

            return "<div class='box' title='$" + attr.cost + "'>" + attr.item + "</div>";
        }
    }
});

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.