How do I add an ng-click to an element? - angularjs

I have an HTML element that I cannot directly make changes to.
How would I add an ng-click event to it?
E.g.
<div id="myDiv"><img src="my/img/src/jpg"/></div>
How would I add an ng-click to the div? Jquery or vanilla JS answers, please.

Okay, I worked out that, as the element is being provided by a service, it doesn't exist on page load, so I have to try another way to do this.
The answer, in other circumstances, would be:
$("#myDiv").attr("ng-click", "myFunction()");
$compile($("#myDiv"))($scope);
Just make sure your element exists, when you try to add something to it!

If you're not restricted to using an ID on your element (...if you could use a class instead), then you could write a directive to bind the click handler.
You would write the directive to restrict it to that class:
<div class="myClass"><img src="my/img/src/jpg"/></div>
angular.module('myModule', [])
.directive('myClass', function () {
return {
restrict: 'C', // <-- restrict to classname
link: function (scope, el) {
el.on('click', function () {
// do stuff
})
}
};
})
This would bind a click to any element with myClass added to it.

Related

AngularJs Directive don't update itself for source element's attribute updates

tried almost everything but not succeed.
I wanted to take an action only if I click on an element whose class name is "ion-android-favorite-outline".
My source element is like below
<i id="{{product.product_code}}" class="icon ion-android-favorite-outline"></i>
I am able to do it using "restrict:'C'" in the directive code.
In the directive, once I am done with data processing, I am changing source element's class to "ion-android-favorite" as below.
.directive(
"ionAndroidFavoriteOutline",
function(sessionStorageService, productService){
return{
restrict: 'C',
link: function(scope, element, attrs) {
element.bind("click" , function(e){
var productCode = attrs.id;
console.log(attrs.class); // on every click i get class name as 'ion-android-favorite-outline' event though html has class name as 'ion-android-favorite'
if (sessionStorageService.isLoggedIn()) {
productService.trackProduct(productCode).then(function(response){
if (response.data.status == "success") {
element.removeClass("ion-android-favorite-outline").addClass("ion-android-favorite");
} else {
element.removeClass("ion-android-favorite").addClass("ion-android-favorite-outline");
}
});
scope.$apply();
}
I can see source element's class name getting changed and its reflection in the UI as well.
However, if I again click on the source element (whose class is changed in previous click action ) still invokes the directive code.
Why ???
I tried scope.$apply , replace: true etc ... but no workaround.
Plz help.
You can use directive like below:
<i id="{{product.product_code}}" class="ion-android-favorite-outline" ion-android-favorite-outline></i>
#stephan, answered correctly.
element.unbind("click");

Adding class to element using Angular JS

I know how to add a class on click of a button in 'jQuery'
$('#button1').click(function(){
$('#div1').addClass('alpha');
});
I want to achieve same thing by angular js. I have a controller - myController1. Can someone help me do it eazily?
AngularJS has some methods called JQlite so we can use it. see link
Select the element in DOM is
angular.element( document.querySelector( '#div1' ) );
add the class like .addClass('alpha');
So finally
var myEl = angular.element( document.querySelector( '#div1' ) );
myEl.addClass('alpha');
You can use ng-class to add conditional classes.
HTML
<button id="button1" ng-click="alpha = true" ng-class="{alpha: alpha}">Button</button>
In your controller (to make sure the class is not shown by default)
$scope.alpha = false;
Now, when you click the button, the $scope.alpha variable is updated and ng-class will add the 'alpha' class to your button.
Use the MV* Pattern
Based on the example you attached,
It's better in angular to use the following tools:
ng-click - evaluates the expression when the element is clicked (Read More)
ng-class - place a class based on the a given boolean expression (Read More)
for example:
<button ng-click="enabled=true">Click Me!</button>
<div ng-class="{'alpha':enabled}">
...
</div>
This gives you an easy way to decouple your implementation.
e.g. you don't have any dependency between the div and the button.
Read this to learn about the MV* Pattern
Try this..
If jQuery is available, angular.element is an alias for the jQuery function.
var app = angular.module('myApp',[]);
app.controller('Ctrl', function($scope) {
$scope.click=function(){
angular.element('#div1').addClass("alpha");
};
});
<div id='div1'>Text</div>
<button ng-click="click()">action</button>
Ref:https://docs.angularjs.org/api/ng/function/angular.element
First thing, you should not do any DOM manipulation in controller function.
Instead, you should use directives for this purpose. directive's link function is available for those kind of stuff only.
AngularJS Docs : Creating a Directive that Manipulates the DOM
app.directive('buttonDirective', function($timeout) {
return {
scope: {
change: '&'
},
link: function(scope, element, attrs) {
element.bind('click', function() {
$timeout(function() {
// triggering callback
scope.change();
});
});
}
};
});
change callback can be used as listener for click event.
querySelector is not from Angular but it's in document and it's in all DOM elements (expensive). You can use ng-class or inside directive add addClass on the element:
myApp.directive('yourDirective', [function(){
return {
restrict: 'A',
link: function(scope, elem, attrs) {
// Remove class
elem.addClass("my-class");
}
}
}
For Angular 7 users:
Here I show you that you can activate or deactivate a simple class attribute named "blurred" with just a boolean. Therefore u need to use [ngClass].
TS class
blurredStatus = true
HTML
<div class="inner-wrapper" [ngClass]="{'blurred':blurredStatus}"></div>
In HTML
To add the class named alpha, assign any variable like showAlpha to false first and then set it to true on click.
<div data-ng-class="{'alpha' : showAlpha}"> </div>
<button ng-click="addClass()"> </button>
In JS file
$scope.showAlpha = false;
$scope.addClass = function(){
$scope.showAlpha = true;
}
try this code
<script>
angular.element(document.querySelectorAll("#div1")).addClass("alpha");
</script>
click the link and understand more
Note: Keep in mind that angular.element() function will not find directly select any documnet location using this perameters
angular.element(document).find(...) or $document.find(), or use the standard DOM APIs, e.g. document.querySelectorAll()

Common directive ng-click guidance needed

I have a directive which consists of a form text element and a continue button along with the associated controller etc. This directive is going to be used in about 5 different pages, but on each page it is used the continue button will do something different.
My question is where can/should I put the code for the continue button if it does different things for each page?
Since its a directive I cant simply pass a different function into ng-click depending on what page im on (ie, if i simply replicated the code on each page it is used I could simply change the function called on ng-click and have that function in each of the page controllers.
Hopefully Im not being too vague with my question and you can make sense of what im asking. If not just say so and ill try to explain in more detail.
I would really appreciate some guidance on this matter.
Thanks.
There are two ways that you can do it. If you are creating your directive as a true component you can use isolated scope with & binding that binds to an expression.
Assume your directive looks like
<div do-work on-click="save()"></div>
and the generated html
<div>
<input ...>
<button ng-click="doAction()"><button>
</div>
The directive scope will be defined
scope:{
onClick:'&'
}
In your directive controller or link function you need to implement the button doAction, which in turns evaluates the onClick action
scope.doAction=function() {
scope.onClick({//if params are required});
}
Now you have linked the parent through the direct onClick reference. One thing to remember here is that this creates a directive with isolated scope.
In case you do not want isolated scope created you need to use
scope.$eval(attr.onClick); // this evaluates the expression on the current scope.
Hope this helps.
Ideally you should not create directives which are not re-usable.
In your case, you may do it like following -
create an isolated scope in the directive
add a function to be called and pass the page/ page id as parameter
call functions in controller based on parameter
Directive
myApp.directive('someDirecive', function () {
return {
// restrict options are EACM. we want to use it like an attribute
restrict: 'A',
// template : <inline template string>
// templateUrl = path to directive template.
// templateUrl: '',
scope: {
onButtonClick : '&'
},
controller: function ($scope, $element, $attrs, $transclude) {
$scope.onButtonClick = function(pageId) {
if (pageId == 1) {
// do something
}
else if (pageId == 2) {
// do something
}
}
},
//link: function (scope, iElement, iAttrs) {
//}
};
});
HTML
<div some-directive on-button-click="DoSomething(1)" />

angularjs: click on a tag to invoke a function and pass the current tag to it

I need to handle a click on a tag that enables the opening of a popover.
I try to figure out the best way to do this with angularjs and naturally used hg-click.
<div ng-repeat="photo in stage.photos"
ng-click="openPopoverImageViewer($(this))"
>
$scope.openPopoverImageViewer = function (source) {
alert("openPopoverImageViewer "+source);
}
The issue is that I cannot manage to pass the $(this) to it.
Q1) How to pass the jQuery element?
Q2) In addition, ng-click sounds
to require the function being part of the controller: is it possible
to invoke a function in the partial instead?
You need to stop "thinking in jQuery" :)
Like #oori says, you can pass in photo.
Or better yet, create a custom directive. Directives is the way to go when you need new functionality in your dom, like an element that you can click to open an overlay. For example:
app.directive('popOver', function() {
return {
restrict: 'AE',
transclude: true,
templateUrl: 'popOverTemplate.html',
link: function (scope) {
scope.openOverlay = function () {
alert("Open overlay image!");
}
}
};
});
You can then use this as a custom elemen <pop-over> or as an attribute on regular HTML elements. Here is a plunker to demonstrate:
http://plnkr.co/edit/P1evI7xSMGb1f7aunh3G?p=preview
Update: Just to explain transclusion: When you say that the directive should allow transclusion (transclude:true), you say that the contents of the tag should be sent on to the directive.
So, say you write <pop-over><span>This will be passed on</span></pop-over>, then the span with "This will be passed on" is sent to the directive, and inserted wherever you put your ng-transclude element in your template. So if your pop-over template looks something like this:
<div>
<ng-transclude/>
</div>
Then your resulting DOM after the template has compiled will look like this:
<div>
<span>This will be passed on</span>
</div>
Pass it "photo"
<div ng-repeat="photo in stage.photos" ng-click="openPopoverImageViewer(photo)">
or the current $index
<div ng-repeat="photo in stage.photos" ng-click="openPopoverImageViewer($index)">

Dynamically change the action of href using angularjs

I'm a newbie to angular, and I'm playing around with it to try and understand how things work. I have an href as part of the template of a directive and an action associated with clicking the link. I would like to know how I can change the action when the user clicks on the link. I tried using a link function in my template, but I couldn't even get it to fire a message to the console.
Here is my link function:
var linkFunction = function(scope) {
scope.$watch(scope.loggedin, function() {
console.log('Here');
});
};
Any pointers? Or is there a better way.
TIA
Link function is part of directive. You can use an ng-click directive in the anchor tag in the template and provide its implementation in the linking function of the directive.
//template
Click Me
//Link function in directive
function(scope) {
scope.doThis = function() {
console.log("doing this);
}
}

Resources