How to catch event onclick without ng-click Angular.js - angularjs

I'm developing an Angular App but I want to catch onclick event without ng-click, I want to use something like that
$scope.onClick(...)

AngularJs use directive to operate dom. you can add a directive like this.
AngularJs
YourApp.directive('testClick', function () {
return {
restrict: 'A',
link: function (scope, element) {
element.onclick = function() {
//do some thing.
}
}
}
})
html
<button test-click>Test Click</button>

Depends on what you're trying to click. If we're talking about normal DOM,you could use the regular, non-angular way of doing this.
I.e.
Assuming for an element like
<div id="elementID" onclick = "clicked">Element</div>
Javascript:
function clicked(){
console.log("I was triggered!");
}
var element = document.getElementById('elementID');
element.onclick = function(){
console.log("I was also triggererd!");
}
Or even use JQuery if you want:
$('#elementID').bind('click', function () {
console.log("I would also be triggered!");
});
Hope this helped!

The only way it worked for me was:
JS:
.directive('testClick', function () {
return {
restrict: 'A',
link: function (scope, element) {
element.on('click', function() {
console.log('Clicked');
})
}
}
})
HTML:
<button test-click> Here </button>

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);
});
}
};
});

Passing ng-click/ng-submit promise to directive

Basically, I created a directive that passes a promise to the link function from ng-click and and detects when the promise is done so that I can attach a class to it.
Example:
.directive('myDirective', function($parse) {
return {
restrict: 'A',
scope: {
ng-click: '&'
},
link: function(scope) {
var d = $parse(scope.ngClick);
element.on('click', function(event) {
d().then(function() {
element.addClass(attrs.myDirective);
});
});
}
};
});
<element ng-click="promise();" my-directive="class"></element>
//controller function
$scope.promise = function() {
return promise().then(function() {});
}
It is doing what I want except that the controller function is getting called three times. I would really like to just use require: '^ngClick' here but since the ngClick directive does not have any controllers, I can't do that. Can anyone point me in the right direction? Thanks!
Added event.preventDefault() to the event.on('click') function in the link of my directive:
element.on('click', function(event) {
event.preventDefault();
d().then(function() {
element.addClass(attrs.myDirective);
});
});

Angular Custom Directive Call Inline Function

I am building a custom directive somehow like this
app.directive('confirmation', function() {
return {
restrict: 'A',
scope: {
onConfirm:"&"
},
link: function (scope, element) {
$(element).confirmation(function(){
onConfirm: function(){
scope.onConfirm();
}
});
}
};
});
and use it like this
<script>
function DoSomethingOnConfirm(){
//Do Something;
}
</script>
<a confirmation on-confirm="DoSomethingOnConfirm()">Delete</a>
I don't have access to the controller so the function "DoSomethingOnConfirm()"
is a normal javascript function, how could I call this function inside the directive, I tried calling it directly but it didn't work.
From your question i understand that you wanted to call a javascript from your directive. I believe in this case you wanted to call some function when user click anchor tag directive.
Here is the code
<script>
var app = angular.module('app', []);
app.directive('confirmation', function() {
return {
restrict: 'A',
link: function (scope, element, attr) {
element.on('click',function(){
eval(attr.fname);
});
}
};
});
function DoSomethingOnConfirm(){
alert("Are you sure want to delete?");
}
function AddMe(){
alert("Added!!!");
}
</script>
<a confirmation href="javascript:;" fname="DoSomethingOnConfirm()">Delete</a>
<a confirmation href="javascript:;" fname="AddMe()">Add</a>
Instead of getting external function name from scope, i am getting it from attribute and triggering that function.
I hope this helps

Angular directive not getting instantiated

I'm trying to create a simple popover directive in angular but it doesn't seem to be working. I'm not sure why but the directive doesn't seem to get instantiated - I'm not even getting the console.log back:
var core = angular.module('core', []);
core.directive('popover', function(){
return {
restrict: 'A',
link: function (scope, el, attrs) {
var isTouchDevice = !!("ontouchstart" in window);
console.log(isTouchDevice);
if (isTouchDevice) {
el.bind("touchstart", function (e) {
console.log('on mobile');
});
} else {
el.bind("mouseover", function (e) {
console.log('on desktop');
});
}
}
};
});
Using it with the following html:
<div ng-app>
<div popover>hover me</div>
</div>
http://jsfiddle.net/nv8eq7n8/
You need not to wrap the script inside the document on jsfiddle (see the upper-left menu, I set it to no wrap - in <body>). Otherwise, the DOM would be loaded before the JS, and thus you get the missing module error.
And yes, as the other answer said, you need to specify the app name.
Here it is, working all fine: http://jsfiddle.net/wx8ydotr/
You missed the app's name:
<div ng-app="core">
It seems the code isn't loading, i had to change the html to:
<script>
var core = angular.module('core', []);
core.directive('popover', function() {
return {
restrict: 'A',
link: function (scope, el, attrs) {
var isTouchDevice = !!("ontouchstart" in window);
console.log(isTouchDevice);
if (isTouchDevice) {
el.bind("touchstart", function (e) {
console.log('on mobile');
});
} else {
el.bind("mouseover", function (e) {
console.log('on desktop');
});
}
}
};
});
</script>
<div ng-app="core">
<div popover>hover me</div>
</div>

Dynamically disable all ng-clicks within an element

I have a directive disable-ng-clicks and under certain conditions, I want to prevent all ng-clicks that are children of the directive. Here is some example markup:
<div disable-ng-clicks> <!-- directive -->
<a ng-click="someAction()"></a>
<div ng-controller="myController">
<a ng-click="anotherAction()"></a>
<a ng-click="moreActions()"></a>
</div>
</div>
If these were normal hyperlinks, I could do something like this in the link function:
function(scope, iElement, iAttrs) {
var ngClicks = angular.element(iElement[0].querySelectorAll('[ng-click]'));
ngClicks.on('click', function(event) {
if(trigger) { // a dynamic variable that triggers disabling the clicks
event.preventDefault();
}
});
}
But this does not work for ng-click directives. Is there another way to accomplish this?
Here is the best I could come up with. I created a new directive to replace ng-click:
directive('myClick', ['$parse', function($parse) {
return {
restrict: 'A',
compile: function($element, attrs) {
var fn = $parse(attrs.myClick);
return function (scope, element, attrs) {
var disabled = false;
scope.$on('disableClickEvents', function () {
disabled = true;
});
scope.$on('enableClickEvents', function () {
disabled = false;
});
element.on('click', function (event) {
if (!disabled) {
scope.$apply(function () {
fn(scope, { $event: event });
});
}
});
};
}
}
}]);
So in a different directive, I can have:
if (condition) {
scope.$broadcast('disableClickEvents');
}
and when I want to re-enable:
if (otherCondition) {
scope.$broadcast('enableClickEvents');
}
I don't like having to use a different directive for ng-click, but this is the best plan I could think of.
You are catching 'click' event on parent only because of JS events bubbling, so if you want to intercept it on all descendants, so your directive should get all descendants of current element, listen their 'click' event and prevent it if necessary.
This directive will iterate over all child elements, check to see if they have an ng-click attribute, and if they do, it will disable any registered click event handlers:
directive('disableNgClicks', function(){
return {
restrict: 'E',
link: function(scope, elem, attrs){
angular.forEach(elem.children(), function(childElem) {
if (childElem.outerHTML.indexOf("ng-click") > -1) {
angular.element(childElem).off('click');
}
});
}
}
})
Plunker demo
I know this is 2 years ago but I needed to do something similar and came up with a rather simple solution.
The object:
items: {
item1 : {
selected: 0,
other: 'stuff'
},
item2 : {
selected : 1,
other: 'stuff'
}
}
The HTML:
<div ng-repeat="item in items" ng-model="item.selected" ng-click="selectParent($event)">
<div ng-click="item.selected ? selectChild($event) : null">Child</div>
</div>
The functions:
$scope.selectParent = function($event) {
var itemScope = angular.element($event.currentTarget)scope().item;
itemScope.selected = !itemScope.selected;
}
$scope.selectChild = function($event) {
$event.stopPropagation;
console.log('I only get triggered if parent item is selected');
}
This is a pretty raw example of what I did. You should probably be using a directive that gives you $scope rather than angular.element($event.currentTarget).scope... either way the simplistic inline if logic is what I was really getting at. You can call a function or not based on some value.

Resources