How can I access $event inside a directive? - angularjs

I can't seem to pass it as an attribute!
I can add an ng-click="function($event)" and pass $event that way to a controller function, but I would like to access it inside a directive.
The ultimate purpose is to stopPropagation() and/or preventDefault() of an element inside a directive instead of in a controller.
EDIT: I will post code accordingly
<div ng-app="myApp" ng-controller="MyCtrl">
<button stop-toggle ng-click="testFunction($event)">
click me
</button>
Hello, {{name}}!
</div>
var myApp = angular.module('myApp',[]);
//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});
function MyCtrl($scope) {
$scope.name = 'Superhero';
$scope.testFunction = function($event){
console.log("you can access the event here:", $event);
$event.stopPropagation();
}
}
myApp.directive('stopToggle', function(){
return {
link: function(scope, elem, attrs){
elem.bind('click', function(){
console.log("how do i access the $event here??");
// elem.stopPropagation(); // invalid function
// elem.preventDefault(); // invalid function
})
}
}
});
http://jsfiddle.net/Lvc0u55v/10656/

var myApp = angular.module('myApp',[]);
myApp.directive('stopToggle', function(){
return {
link: function(scope, elem, attrs){
elem.on('click', function(e){
e.stopPropagation();
e.preventDefault();
})
}
}
});
Just pass event as an argument to the function inside .on()

Related

Can't add ngClick to attribute directive

I want to dynamically add ngClick to an attribute directive.
javascript
angular.module('app')
.directive('myDirective', ['$log', function ($log) {
return {
restrict: 'A', // PAY ATTENTION TO THIS LINE
compile: function (tElement) {
tElement.attr('ng-click', 'onClick()');
return function postLink(scope) {
scope.onClick = function () {
$log.debug('myDirective is clicked');
}
}
}
}
}]);
markup
<button my-directive>Click Me</button>
From the element inspector of Chrome, I can see that the ng-click attribute is added to the button.
I expect to see the text "myDirective is clicked." in the console when the button is clicked, but actually there's nothing printed. No error is raised. Anyone can help? Thanks in advance.
Rather than using link inside compile use the link function directly as shown below
link: function(scope, element, attrs) {
element.onClick(function(){
$log.debug('myDirective is clicked');
});
}
You can directly add the click handler to the element, you need not bind ng-click directive inside your directive.
Hello please try this one,
HTML:
<div ng-app="angularApp">
<div ng-controller="dirCtrl1">
<button ng-click="clickFun('clicked')">Button</button>
<button my-directive="directive">With directive</button>
</div>
</div>
JS:
.controller('dirCtrl1', function ($scope) {
$scope.clickFun = function (msg) {
console.log(msg);
};
})
.directive('myDirective', function(){
return{
restrict: 'A',
link: function(scope, ele, attr){
var eventName = attr.evetName || 'click';
var mas = attr.myDirective || 'just console';
ele.on(eventName, function(){
console.log(mas);
});
}
};
});

How to update the input text value using custom Directive in angularjs

I am newer in angularjs. I am just trying to update the input txt value using custom Directive. But i cant. Here i have showed my code What i did wrong this code. Some one help me and explain how it is working.
var myApp = angular.module('myApp',[]);
//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});
myApp.controller('MyCtrl',MyCtrl);
function MyCtrl($scope) {
$scope.name = 'Superhero';
$scope.myTime = '10:59';
}
myApp.directive('myDirective', function () {
return {
restrict: 'A',
require: '?ngModel',
link: function (scope, element, attrs, ngModel) {
scope.$watch(attrs.ngModel, function (v) {
console.log('value changed, new value is: ' + v);
ngModel.$setViewValue('11')
//scope.ngModel = '11'
});
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="MyCtrl">
Hello, {{name}}!
<input type="text" my-directive ng-model="myTime" name="customTime">
</div>
You should register your MyCtrl controller in your myApp module like below.
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl',MyCtrl);
function MyCtrl($scope) {
$scope.name = 'Superhero';
$scope.myTime = '10:59';
}
If you need to update the text field value to some desired value, once you're done with the update in the watcher using $setViewValue(), you need to call $render() as well on NgModelController.
link: function (scope, element, attrs, ngModel) {
scope.$watch(attrs.ngModel, function (v) {
console.log('value changed, new value is: ' + v);
ngModel.$setViewValue('11');
ngModel.$render();
});
}
Here's a Pen to check this change.

angularJS how to $eval the function with parameter

I am trying to implement the directive, in the directive, I want to $eval the values which contains the function name and parameter value:
Html page:
<select mydirective="action('pValue')">
AngularJS directive code:
app.directive('mydirective', function ($timeout) {
return {
restrict: 'A',
link: function ($scope, element, attr) {
$timeout(function () {
$scope.$eval(attr.mydirective);
});
}
}
What I am expected is it will invoke the action function define in scope and pass the pValue as function parameter. How can I make it work please?
What you want happen automatically, the function will invoke with the value, this is the purpose of eval:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.action = function(val) {
alert(val);
}
});
app.directive('mydirective', function($timeout) {
return {
restrict: 'A',
link: function($scope, element, attr) {
$timeout(function() {
$scope.$eval(attr.mydirective);
});
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.21/angular.min.js"></script>
<div ng-app="plunker" ng-controller="MainCtrl">
<select mydirective="action('pValue')"></select>
</div>
For those whom looking for a way to pass $event info to custom directive method see example below:
TEMPLATE:
<div on-touch-end="onTouchEnd( 'some data' )">
TOUCH ME!
</div>
CONTROLLER:
$scope.onTouchEnd = function( data ) {
console.log("onTouchEnd event with data", data, event );
};
DIRECTIVE:
.directive('onTouchEnd', function() {
return {
restrict : 'A',
link : function( $scope, $element, $attr ) {
$element.on('touchend', function( event ) {
$scope.$apply(function() {
$scope.$eval( $attr.onTouchEnd );
});
});
}
}
})

Data attribute change not being observed

I'm changing data attribute of a dom element and using $observe within the directive to detect for any changes but it doesn't seem to work after clicking on the "change data" button
HTML
<body ng-controller="MainCtrl">
<div id="container" data-name="somename" mydirective>Data</div>
<button ng-click="changeData();">Change Data Attribute</button>
</body>
JS
app.controller('MainCtrl', function($scope) {
$scope.changeData = function() {
var el = document.querySelector('#container');
angular.element(el).attr('data-name', 'hello');
}
});
app.directive('mydirective', function() {
return {
link : function(scope, element, attrs, ngModel) {
attrs.$observe("name", function (newValue) {
console.log(newValue);
});
}
}
Plnkr : http://plnkr.co/edit/saM7fO0DdsaaDBW7ADQH?p=preview
why dont you use expression data-name="{{datax}}" ?
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.datax = "somename";
$scope.changeData = function() {
//var el = document.querySelector('#container');
//angular.element(el).attr('data-name', 'hello');
$scope.datax = "hello";
}
});
app.directive('mydirective', function() {
return {
link : function(scope, element, attrs, ngModel) {
attrs.$observe("name", function (newValue) {
console.log(newValue);
});
}
}
});

Angular does not update bound property

Fiddle
HTML:
<div ng-controller="MyCtrl">
<button my-event-directive>Click me</button>
<div>{{secret}}</div>
</div>
JS:
var myApp = angular.module('myApp',[]);
myApp.directive('myEventDirective', function() {
return {
link: function(scope, element) {
element.on('click', function(event){
scope.$emit('myEvent', {secret: 'aaa'});
});
}
}
})
function MyCtrl($scope) {
$scope.secret = 'bbb';
$scope.$on('myEvent', function(event, data){
alert('event received!');
$scope.secret = data.secret;
});
}
After I click the button, the event is received in the controller (alert shows up). However, the {{secret}} binding does not update its value. Why?
My event creation is more sophisticated in real code, of course.
As #Cherinv replied in a comment, when changing a scope attributes outsite the Angular $apply method, you have to call it manually. #runTarm also suggested that the event dispatcher should use the $apply because listeners are freed from remember it then. So:
scope.$emit('myEvent', {secret: 'aaa'});
should be changed to:
scope.$apply(function() {
scope.$emit('myEvent', {secret: 'aaa'});
});
$apply method is described in details in the following article: http://jimhoskins.com/2012/12/17/angularjs-and-apply.html
USE $scope.$apply(). NOW the change will be noticed, and the page is updated.
var myApp = angular.module('myApp',[]);
myApp.directive('myEventDirective', function() {
return {
link: function(scope, element) {
element.on('click', function(event){
scope.$emit('myEvent', {secret: 'aaa'});
});
}
}
})
function MyCtrl($scope) {
$scope.secret = 'bbb';
$scope.$on('myEvent', function(event, data){
alert('event received! secret is ' + data.secret);
$scope.$apply(function () {
$scope.secret = data.secret;
});
});
}
You could try changing binding to happen on object.value rather than value. Maybe it's the case when angular can not trace immutable property change.
<div ng-controller="MyCtrl">
<button my-event-directive>Click me</button>
<div>{{data.secret}}</div>
</div>
var myApp = angular.module('myApp',[]);
myApp.directive('myEventDirective', function() {
return {
link: function(scope, element) {
element.on('click', function(event){
scope.$emit('myEvent', {secret: 'aaa'});
});
}
}
})
function MyCtrl($scope) {
$scope.data = {
secret: 'bbb'
};
$scope.$on('myEvent', function(event, data){
alert('event received!');
$scope.data.secret = data.secret;
});
}
This should work.
P.S. since you always see alert being called that means that you don't need to call scope.$apply to invoke scope digest and the value IS assigned, the problem is that angular can not watch on immutable values (probably)

Resources