Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

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>
share|improve this question
add comment

2 Answers

up vote 1 down vote accepted

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";
  });
});
share|improve this answer
    
Thanks. I thought the link fn will automatically update. –  Charles Jan 28 at 7:33
    
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 Jan 28 at 7:42
    
@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. –  Josh Jan 28 at 12:58
    
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 Jan 29 at 20:09
    
@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. –  Josh Jan 30 at 1:09
show 1 more comment

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

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.