Reputation: 5087
I was trying to write a directive which allows us to delete values from a list. The HTML and Javascript code are as follows
HTML
<body ng-app="evalModule">
<div ng-controller="Ctrl1">
<input type="text" ng-model="newFriend"></input>
<button ng-click="addFriend()">Add Friend</button>
<ul>
<li ng-repeat="friend in friends">
<div class='deletable' index-value = {{$index}} delete-function="removeFriend(frndToRemove)"> {{$index}} {{friend}} </div>
</li>
</ul>
</div>
</body>
Javascript
function Ctrl1 ($scope) {
$scope.friends = ["Jack","Jill","Tom"];
$scope.addFriend = function () {
$scope.friends.push($scope.newFriend);
}
$scope.removeFriend = function (indexvalue) {
console.log(indexvalue);
var index = $scope.friends.indexOf(indexvalue);
$scope.friends.splice(indexvalue, 1);
}
}
var evalModule = angular.module("evalModule",[]);
evalModule.directive('deletable', function(){
return{
restrict : 'C',
replace : true,
transclude : true,
scope:{
indexValue : '@indexValue',
deleteFunction : '&'
},
template : '<div>'+
'<div> X </div>'+
'<div ng-transclude></div>'+
'</div>',
link:function(scope, element, attrs){
var del = angular.element(element.children()[0]);
del.bind('click',deleteValue);
function deleteValue () {
var expressionHandler = scope.deleteFunction;
expressionHandler({frndToRemove : scope.indexValue});
console.log("deleteValue called with index" + attrs.indexValue);
scope.$apply();
}
}
}
});
Why do I need to call scope.$apply even though the code is bound as an event to button click event. According to the docs here http://docs.angularjs.org/guide/scope this should be part of "Angular realm".
Can somebody help me understand angular realm while clarifying the above? Any feedback on improving the above code would also appreciated.
Upvotes: 1
Views: 350
Reputation: 14104
As @DavinTyron said, a button click event is an outside event, not part of "Angular realm". So you need to call $scope.$apply()
in order to trigger a digest cycle and update the DOM.
In your case, though, you don't need to bind the click event manually. You may use ng-click
instead:
template: '<div>'+
'<div ng-click="delete()"> X </div>'+
'<div ng-transclude></div>'+
'</div>',
link: function(scope) {
scope.delete = function () {
scope.deleteFunction({frndToRemove : scope.indexValue});
console.log("deleteValue called with index" + attrs.indexValue);
};
}
Since ng-click
is being used, there's no need to call $scope.$apply()
. Here's a modified version of your jsFiddle.
Upvotes: 4