105

I am trying to attach click event to anchor tags (coming from ajax) and block the default redirection. How can I do it in angular ?

<ul>
    <li><a href="/abc"><p>abc</p></a></li>
    <li><a href="/abc1"><p>abc1</p></a></li>
    <li><a href="/abc2"><p>abc2</p></a></li>
    <li><a href="/abc3"><p>abc3</p></a></li>
</ul>

In ts file:

constructor(elementRef: ElementRef, renderer: Renderer) { 
    this.listenFunc = renderer.listen(elementRef.nativeElement, 'click', (event) => {
        event.preventDefault();
        let target = event.target || event.srcElement || event.currentTarget;
        console.log(target);
    });  
}

This will attach event to all elements, how can I limit this to anchor tag only ?

All helps appreciated.

HDJEMAI
  • 9,436
  • 46
  • 67
  • 93
  • 1
    you can use `event.target.nodeName` to know on which HTML tag click is fired. – ranakrunal9 Jan 04 '17 at 08:01
  • `(click)='fn'` can be used. – Jai Jan 04 '17 at 08:27
  • @jai thanks i can't manipulate the ajax response i have to handle it from ts file –  Jan 04 '17 at 08:58
  • Seems you have to manipulate the JSON you get. parse it to an object; add or update properties and then assign updated JSON to target; maybe this gives you a hint: http://stackoverflow.com/questions/8702474/updating-a-json-object-using-javascript – Karl Jan 04 '17 at 16:34
  • Can you explain how you get this HTML from ajax and insert it into the page? AHAH (AJAX HTML) used to be quite popular, even with Angularjs 1.x many templates were rendered on the serverside. Just haven't seen any use of AHAH with modern Angular or React. – Martin May 30 '17 at 13:07

16 Answers16

158

You can use routerLink (which is an alternative of href for angular 2+) with click event as below to prevent from page reloading

<a [routerLink]="" (click)="onGoToPage2()">Go to page</a>
Vicky
  • 2,008
  • 2
  • 11
  • 19
  • 4
    [routerLink] is for internal urls. What if we want to send the user to an external url and at the same time watch the click event? – Marzieh Bahri Mar 11 '18 at 05:14
  • 1
    You can use the same above code in HTML and in `component.ts` file use `onGoToPage2() { window.location.href='http://www.cnn.com/'; //use the external url here }` so,you can watch the click event also. – Vicky Mar 15 '18 at 09:07
  • 3
    Seems that the square brackets around routerLink are required for it to work as desired (without them it navigates as normal to /). – Neofish Mar 29 '18 at 10:58
  • 3
    Works perfectly in Angular 7 – Jette Dec 20 '18 at 10:34
  • @emirhosseini are you using it explicitly as `[routerLink]` and not `routerLink` ? that was tripping me up. – Captain Prinny Oct 25 '19 at 20:40
  • 2
    this fails miserably when your route has query parameters i'll save you the scrolling, keep using `href="javascript:void(0)"`. – Stavm Nov 11 '19 at 21:25
  • Note : [routerLink]="" will keep address bar path unchanged while routerLink="" will change the path in address bar (I have discovered this in edge case of headless model architecture where routing is not used - instead API would act as router). – StefaDesign Jul 06 '22 at 17:30
31

I think you are not letting Angular work for you.

In angular 2:

  1. Remove the href tag from <a> to prevent a page forwarding.
  2. Then just add your usual Angular click attribute and function.
  3. Add to style: "cursor: pointer" to make it act like a button
Vicky
  • 2,008
  • 2
  • 11
  • 19
PatrickW
  • 357
  • 3
  • 4
  • 10
    But that doesn't make it render like a link. It just looks like normal paragraph text. – Neutrino Oct 03 '17 at 09:45
  • 2
    you can control looks with CSS. What do you want your link to look like? – PatrickW Oct 17 '17 at 14:49
  • 10
    A link, and I'd rather not have to mess around with manual styling just to make a link look like a link, as it should do anyway. – Neutrino Oct 31 '17 at 13:55
  • 5
    When adding a style to HTML you use an equal sign e.g. `style="cursor: pointer;"` – Mike Poole Feb 07 '19 at 09:06
  • 4
    a click listener with corresponding implementation is not the same as an href. you can not open a new tab with it for example. please dont replace all links in this world with click listeners - you are making the web a worse place this way. – Patrick Kelleter Feb 16 '21 at 09:39
  • 1
    This is really a bad way, because it does not take accessibility into account. The link is not focusable. – Sebi2020 Oct 26 '22 at 08:01
25

I've been able to get this to work by simply using [routerLink]="[]". The square brackets inside the quotes is important. No need to prevent default actions in the method or anything. This seems to be similar to the "!!" method but without needing to add that unclear syntax to the start of your method.

So your full anchor tag would look like this:

<a [routerLink]="[]" (click)="clickMethod()">Your Link</a>

Just make sure your method works correctly or else you might end up refreshing the page instead and it gets very confusing on what is actually wrong!

BlueCaret
  • 4,719
  • 7
  • 30
  • 48
17

You just need to add !! before your click method handler call: (click)="!!onGoToPage2()". The !! will prevent the default action from happening by converting the return of your method to a boolean. If it's a void method, then this will become false.

Andrew Landsverk
  • 673
  • 7
  • 17
  • 14
    I learned the hard way that abusing this can make very confusing errors to other developers in the long run. When something in your onGoToPage2 function crashes, the anchor automatically redirects you to your home page which doesn't make any sense... using $event.preventDefault() at the beggining will produce more consistent crashes for other developers to figure out. – Ziul Sep 06 '18 at 02:14
  • 1
    This is really a bad way, because it does not take accessibility into account. The link is not focusable. – Sebi2020 Oct 26 '22 at 08:01
14

I had issues with the page reloading but was able to avoid that with routerlink=".":

<a routerLink="." (click)="myFunction()">My Function</a>

I received inspiration from the Angular Material docs on buttons: https://material.angular.io/components/button/examples

UPDATE I've started using routerLink="" since Angular 12. I was finding that routerLink="." was routing me to a parent page.

Mike Dalrymple
  • 993
  • 12
  • 23
13
<a href="#" (click)="onGoToPage2()">Go to page 2</a>
Neutrino
  • 8,496
  • 4
  • 57
  • 83
12

You can try something like this:

<a href="javascript: void(0);" (click)="method()">

OR

<a href="javascript: void(0);" [routerLink]="['/abc']">
Akj
  • 7,038
  • 3
  • 28
  • 40
Gaspar
  • 1,515
  • 13
  • 20
9

<a href="javascript:void(0);" (click)="onGoToPage2()">Go to Page 2</a>

aungye
  • 2,219
  • 1
  • 15
  • 6
  • 3
    This question was asked over a year ago. It is unlikely that the Original Poster is still having this same issue, and therefore new answers should strive to provide as much detail as possible to show how the answer helps others who are having the same issue. This answer is more like a comment than a complete, researched, explained answer. – Claies Jan 13 '18 at 19:32
6

I have encountered this issue in Angular 5 which still followed the link. The solution was to have the function return false in order to prevent the page being refreshed:

html

<a href="" (click)="openChangePasswordForm()">Change expired password</a>

ts

openChangePasswordForm(): boolean {
  console.log("openChangePasswordForm called!");
  return false;
}
Alexei - check Codidact
  • 22,016
  • 16
  • 145
  • 164
  • 1
    So it still regards the return value of the function ... not as clear as in the vanilla JS onClick="return function()" ... – rubmz Mar 18 '20 at 15:09
3

I was able to implement this successfully

<a [routerLink]="['/login']">abc</a>
Jaimin Patel
  • 161
  • 9
3

I had to combine several of the answers to get a working solution.

This solution will:

  • Style the link with the appropriate 'a' styles.
  • Call the desired function.
  • Not navigate to http://mySite/#

    <a href="#" (click)="!!functionToCall()">Link</a>

Francisco d'Anconia
  • 2,436
  • 1
  • 19
  • 25
3

Clean way to handle anchor tags and href and keeping your anchor styling:

html:

Pass in the $event on click

<a href (click)="doSomething($event)">Do something</a>

Typescript:

Get the event as MouseEvent and call e.preventDefault()

doSomething(e: MouseEvent): void {
    e.preventDefault();

    //Do something
}

Your styling will stay in tact and no default browser anchor handling will take place.

Pierre
  • 8,397
  • 4
  • 64
  • 80
2

You can use routerLink which is an alternative of href for angular 2.** Use routerLink as below in html

<a routerLink="/dashboard">My Link</a>

and make sure you register your routerLink in modules.ts or router.ts like this

const routes: Routes = [
  { path: 'dashboard', component: DashboardComponent }
]
Vicky
  • 2,008
  • 2
  • 11
  • 19
1

While the question is technically already answered I think all answers here forget something important: Just adding a click-handler is not enough. You also want the link to be usable for people who only use the keyboard for Accessibility reasons. Usually this means that hitting Enter while focussing the element should have the same effect as clicking on it. While we're at it we could also set the role. If the link is actually used as a button we should set role="button" - this way screenreaders will announce it as a button and not a navigation-link. For the original problem: Almost all answers here seem to work for me, but i chose the one with the empty routerLink - I think it makes it semantically clear that no navigation is wanted. Other solutions could lead to confusions later (lets say someone reads your code in a year).

<a [routerLink]="" (click)="doSomething()" (keyup.enter)="doSomething()" role="button" tabindex="0">your link</a>
Mario B
  • 2,102
  • 2
  • 29
  • 41
  • I don't think you need to bind to keyup.enter, because usually a browser emits a click event, if the user presses enter while a link has the focus. – Sebi2020 Oct 26 '22 at 08:05
1

This worked for me:

<a class="btn-link" (click)="clickedFunction()">Click me</a>
Mohammad Zaid Pathan
  • 16,304
  • 7
  • 99
  • 130
0

I have examined all the above answer's, We just need to implement two things to work it as expected.

Step - 1: Add the (click) event in the anchor tag in the HTML page and remove the href=" " as its explicitly for navigating to external links, Instead use routerLink = " " which helps in navigating views.

<ul>
  <li><a routerLink="" (click)="hitAnchor1($event)"><p>Click One</p></a></li>
  <li><a routerLink="" (click)="hitAnchor2($event)"><p>Click Two</p></a></li>
</ul>

Step - 2: Call the above function to attach the click event to anchor tags (coming from ajax) in the .ts file,

  hitAnchor1(e){
      console.log("Events", e);
      alert("You have clicked the anchor-1 tag");
   }
  hitAnchor2(e){
      console.log("Events", e);
      alert("You have clicked the anchor-2 tag");
   }

That's all. It work's as expected. I created the example below, You can have a look:-

https://stackblitz.com/edit/angular-yn6q6t

Naheed Shareef
  • 1,011
  • 7
  • 5