6

I am trying to create a directive with a link function where it can change the "varName" in the scope (i.e. in the input tag). Note the directive template has same "varName" as in the controller & no scope property is used.

Here is what happened:

Case 1: If I click the custom element, the "runFn" function defined in the $scope gets called, however the "varName" is not changed.

Case 2: If I click the div tag, the "runFn" function also gets called AND the "varName" is changed.

I have tried 3 approaches but can't seem to get the link function to change the "varName" value. Can someone explain why n provide a solution please? Thanks.

Code:

<body ng-app="moduleA">
<div ng-controller="ctrlA"> 
    <input type="text" ng-model="varName">
    <custom></custom>
    <div ng-click="runFn()">click for new value</div>
</div>  
<script>
window.onload=(function(){  
    "use strict";
    var app = angular.module('moduleA', []);
    app.controller("ctrlA", function($scope){
        $scope.varName = "old value";
        $scope.runFn = function(){
            $scope.varName = "new value";
            console.log("run fn");
        };
    });
    app.directive("custom", function(){
        return {
            restrict: "E",          
            template: '<div>{{varName}}</div>',
            replace: true,  
            link: function(s, e, a){
                e.on("click", function(){ 
                    s.varName = "new value";   //didn't work
                    s.runFn();        //didn't work
                    s.runFn.call(s);  //didn't work
                });
            }
        };

    });     
})(); // end windows onload
</script>
</body>

2 Answers 2

12

I think all you are forgetting is to call $apply when you make the updates to ensure that the UI is updated.

e.on("click", function(){
  //Call $apply to ensure a $digest loop
  // get's kicked off
  s.$apply(function(){
    s.varName = "new value";
  });
});
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks. I thought the link fn will automatically update.
just wondering if there is any way to simplify overall syntax, from the link function perspective? I mean there are 3 functions nested inside the directive, 2 nested inside the link function.
@Charles - I know it looks a little cludgy, but directives are low level guys anyway. They are meant to hide all the nasty DOM manipulation from the application code. It really depends on what you are doing in your directive that will decide how complex it is. If it is too complex you can always use a Directive Controller.
Perhaps that's where AngularJS is "opinionated"? - from my experience most of my time is spent on adapting the "habbit" of code organisation, rather than functionality.
@Charles - I'm not 100% what you mean by code organization. Your controllers and services are really where business functionality resides. If you need to do more advanced DOM stuff then you put it into a directive and let data binding handle the rest. You need to learn the core concepts of how angular works, e.g. (Dependency injection, digest loops, scope). Once you have that down, Angular makes it a lot faster to build apps in my opinion.
1

Your click function in executed out of angular. You need to handle click event in angular way. Change your directive as follows

app.directive("custom", function(){
    return {
        restrict: "E",          
        template: '<div ng-click="divClick()">{{varName}}</div>',
        replace: true,  

        link: function(s, e, a){

          s.divClick = function(){          
              s.varName = "new value";
              s.runFn();       
              s.runFn.call(s);  
            }
        }
    };
});

JSBIN

Comments

Your Answer

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