I haven't touched angular js in a while and back when I did write, we used a flavour with typescript which was pretty straightforward with me. Now I want to write vanilla angular js and I feel I am a bit confused.
Problem:
I have a directive with a few variables in its isolate scope and I basically want to bind to this directive that is spawned inside a for each <ul>
to a click event. I tried with directly binding a function on ng-click and with link element e.t.c. bind on click, but it seems I am doing something wrong since with the first way nothing happens, with the second way the two-way bound variable is undefined.
Here it goes: https://plnkr.co/edit/OOBMs8pYONLjUE9lQXla?p=preview
activity-header.html
<div>
<h4>
Activity Name: {{activity.activity_name}}
</h4>
<h6>
Activity Start Date: {{activity.activity_start_date}}
</h6>
<h6>
Activity End Date: {{activity.activity_end_date}}
</h6>
<h6>
Participants: {{activity.participants}}
</h6>
</div>
activity-header.js
var app = angular.module('mainApp');
/*
app.controller('activityHeaderCtrl', ['$scope', function($scope) {
$scope.activity='';
$scope.msg='';
$scope.check = function() {
alert($scope.msg);
};
}]);
*/
app.directive('activityHeader', function() {
return {
restrict: 'AE',
templateUrl: 'activity-header.html',
controller: ['$scope', Controller],
scope: {
activity:'=',
msg:'='
},
link: function($scope, $element, attrs) {
$element.bind('click', function($scope) {
alert($scope.msg);
})}
};
function Controller($scope) {
$scope.check = function() {
alert($scope.msg);
};
}
});
index.html
<html ng-app="mainApp">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="script-main.js"></script>
<script src="activity-header.js"></script>
<body>
<div ng-controller="ctrl">
<h1>
Major Bla bla System
</h1>
<ul>
<li ng-repeat="x in events">
<div activity-header activity="x" msg="greetingsfriend" ng-click="check()"></div>
</li>
</ul>
<h6>
Beta v.0.2
</h6>
</div>
</body>
</html>
script-main.js
var app = angular.module('mainApp', []);
app.controller('ctrl', function ($scope) {
//$scope.events = ["Elections", "Protest", "Martial Law", "X-mas Celebration"];
$scope.events = [
{"activity_name": "Elections", "activity_start_date": "31/12/2014", "activity_end_date": "31/12/2015", "participants": "1453"},
{"activity_name": "Martial Law", "activity_start_date": "31/12/2014", "activity_end_date": "31/12/2015", "participants": "1821"},
{"activity_name": "Protest", "activity_start_date": "31/12/2014", "activity_end_date": "31/12/2015", "participants": "1940"},
{"activity_name": "X-mas Celebration", "activity_start_date": "31/12/2014", "activity_end_date": "31/12/2015", "participants": "2009"}
];
$scope.salute = function () {
alert('hello there');
};
});
(By the way, I'm using Mozilla Firefox, otherwise I'd have to host it e.g. on node.js for the same origin policy, don't know how to turn it off in chrome/ internet explorer).
Any idea on how to handle the click?
Your problem is that you are using $scope
as the name for the first argument in the click handler function. That name is overriding the $scope
argument from the linking function.
//BAD
link: function($scope, $element, attrs) {
$element.bind('click', function($scope) {
alert($scope.msg);
})}
Fix your code like this:
//GOOD
link: function(scope, element, attrs) {
element.on('click', function clickHandler(event) {
console.log(scope.msg);
});
}
AngularJS jqLite invokes the click handler with a JQuery Event Object as the first argument not $scope
.
Is this the correct way to handle events on directives?
Why doesn't theng-click
event ever work to call the function I have in my directive's controller?
The ng-click
directive binds to functions in the parent scope.
To bind click events to functions on the directive's scope, use element.on()
. It's how ng-click
gets the event from the browser. Look at the source code.