3

So I have this filter directive:

app.directive('filter', function(){
  return {
    restrict: 'E',
    transclude: true,
    scope: {
        callFunc: '&'
    },
    template:
            '   <div>' +
            '       <div ng-transclude></div>' +
            '   </div>',
    controller: function($scope, $element, $attrs){
        this.getData = function() {
            $scope.callFunc()
        }
    }
  }   
});

app.directive('positions', function(){
  return {
    require: '^filter', 
    scope: {
        selectedPos: '='
    },
    template:
            '  Positions: {{selectedPos}}' +
            '  <ul>' +
            '   <li ng-repeat="pos in positions">' +
            '           <a href="#" ng-click="setPosition(pos); posRegData()">{{pos.name}}</a></a>' +
            '       </li>' +
            '  </ul>',
    controller: function($scope, $element, $attrs){
          $scope.positions = [
            {name: '1'},
            {name: '2'},
            {name: '3'},
            {name: '4'},
            {name: '5'}
          ];
          $scope.selectedPos = $scope.positions[0].name;
          $scope.setPosition = function(pos){
            $scope.selectedPos = pos.name;
          };

    },
    link: function(scope, element, attrs, filterCtrl) {
        scope.posRegData = function() {
            filterCtrl.getData();
        }
    }
  }   
})

And the controller:

app.controller('keyCtrl', ['$scope', function($scope) {
  var key = this;
  key.callFunc = function() {
    key.value = key.selectedPos;
    console.log(key.selectedPos)
  }
}]);

The main question is why the key.selectedPos in the controller get's the right value only on the second click?

Here is a plunker replicating my issue.


One way of doing it is to send a param when calling callFunc()

Then, I update the func in the ctrl: key.callFunc = function(filterParams), but also, I am updating the passed method call-func="key.callFunc(filterParams)

Then in filter directive I change getData method to:

this.getData = function(val) {
  $scope.callFunc({filterParams: val})
}

In positions directive I pass the value that I need:

scope.posRegData = function() {
  filterCtrl.getData({position: scope.selectedPos});
}

Finally, in keyCtrl I get the value like this:

key.callFunc = function(filterParams) {
  key.value = filterParams.position;
  console.log(filterPrams.position)
}

Here is a plunker demonstrating this attempt.

The question in this case is if this is a good way of doing it, keeping in mind it's within a very large application.

1
  • 1
    If you want to share data between controllers or directives. Using a service is almost always the best route to take Commented May 20, 2015 at 13:34

1 Answer 1

3

That's because how isolated scopes work. The parent scope (the controller in your case) will be updated when the digest cycle runs, which is after your ng-click function called the callFunc. So you can put your callFunc code in a $timeout and it will work (but will cause another digest cycle).

Another solution will be to put the value in an object, so when you change the object the controller (which have the reference) will see the update immediately:

In the controller:

key.selectedPos = { value: {}};

key.callFunc = function() {
    key.value = key.selectedPos.value;  
    console.log(key.selectedPos.value)
} 

In the directive:

$scope.selectedPos.value = $scope.positions[0].name;
$scope.setPosition = function(pos){
    $scope.selectedPos.value = pos.name;
};

See this plunker.

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

1 Comment

I was going to talk about $scope.$apply() but i know it's not a good practice. Thx for the object trick. I'll keep that in mind.

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.