Wednesday, June 5, 2024
 Popular · Latest · Hot · Upcoming
98
rated 0 times [  100] [ 2]  / answers: 1 / hits: 7761  / 10 Years ago, mon, june 2, 2014, 12:00:00

I'm having a problem trying to grasp why two way data binding is't working in my custom directive?



The codez:



Directive code:



.directive('invoiceFilter', function () {
return {
restrict: 'E',
replace: true,
templateUrl: '_invoice-filter.tpl.html',
scope: {
selectedItem: '=',
selectedItemChange: '&'
},
link: function(scope) {

scope.items = {
all: 'Show all invoices',
draft: 'Show drafts only',
open: 'Show open invoices',
paid: 'Show paid invoices'
};

scope.raiseSelectedItemChange = function (key) {


alert('Selected item in directive: ' + key + (which seems to work!));

scope.selectedItem = key;
scope.selectedItemChange();

};

}
};
});


Directive template



<div class=btn-group dropdown>
<button class=btn dropdown-toggle type=button id=dropdownMenu1 data-toggle=dropdown>
{{ items[selectedItem || 'open' ] }}
<span class=caret></span>
</button>
<ul class=dropdown-menu role=menu aria-labelledby=dropdownMenu1>
<li ng-repeat=(key, value) in items>
<a href=javascript:void(0) ng-click=raiseSelectedItemChange(key)>{{ value }}</a>
</li>
</ul>
</div>


As you can see I'm just adding some data to the scope (in the link function) and relying on the behavior of ng-repeat and ng-click to raise an event/callback when an item is selected. The alert correctly displays the selected item.



But when I start using the directive like this:



HTML



  <body ng-controller=MainController>
<h1>Hello Plunker!</h1>
<invoice-filter selected-item=filter selected-item-change=filterChange()></invoice-filter>
</body>


Controller



    .controller('MainController', function($scope) {

$scope.filter = all;

$scope.filterChange = function() {

alert(Selected item in controller: + $scope.filter + (does not work, databinding problem???));

};

})


The $scope.filter value never gets updated with the item I selected in the directive, even though I specified '=' on the directive scope which to my understanding should enable two way data binding, right?



What am I missing here?



Plunk playground



Here's a plunkr with the setup described above, so you can verify that it doesn't work :o/



Thanks to anyone who can help!


More From » angularjs

 Answers
8

The two-way binding works, but happens on the next cycle. That's why when you reproduce it again, the value of the last cycle is shown. This is because AngularJS has no chance to run its data binding inbetween the line where you set the value and the line where you call the callback. JavaScript, in that sense, doesn't allow intervention, yet.



Changing scope.selectedItemChange(); to $timeout(scope.selectedItemChange); is an easy fix (don't forget to inject $timeout), by forcing the callback to be called on the next cycle.


[#44879] Saturday, May 31, 2014, 10 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
alanisannettep

Total Points: 695
Total Questions: 96
Total Answers: 91

Location: Australia
Member since Sat, May 27, 2023
1 Year ago
;