Passive Link in Angular 2 - <a href=""> equivalent

219,311

Solution 1

If you have Angular 5 or above, just change

<a href="" (click)="passTheSalt()">Click me</a>

into

<a [routerLink]="" (click)="passTheSalt()">Click me</a>

A link will be displayed with a hand icon when hovering over it and clicking it won't trigger any route.

Note: If you want to keep the query parameters, you should set queryParamsHandling option to preserve:

<a [routerLink]=""
   queryParamsHandling="preserve"
   (click)="passTheSalt()">Click me</a>

Solution 2

That will be same, it doesn't have anything related to angular2. It is simple html tag.

Basically a(anchor) tag will be rendered by HTML parser.

Edit

You can disable that href by having javascript:void(0) on it so nothing will happen on it. (But its hack). I know Angular 1 provided this functionality out of the box which isn't seems correct to me now.

<a href="javascript:void(0)" >Test</a>

Plunkr


Other way around could be using, routerLink directive with passing "" value which will eventually generate blank href=""

<a routerLink="" (click)="passTheSalt()">Click me</a>

Solution 3

There are ways of doing it with angular2, but I strongly disagree this is a bug. I'm not familiarized with angular1, but this seems like a really wrong behavior even though as you claim is useful in some cases, but clearly this should not be the default behavior of any framework.

Disagreements aside you can write a simple directive that grabs all your links and check for href's content and if the length of it it's 0 you execute preventDefault(), here's a little example.

@Directive({
  selector : '[href]',
  host : {
    '(click)' : 'preventDefault($event)'
  }
})
class MyInhertLink {
  @Input() href;
  preventDefault(event) {
    if(this.href.length == 0) event.preventDefault();
  }
}

You can make it to work across your application by adding this directive in PLATFORM_DIRECTIVES

bootstrap(App, [provide(PLATFORM_DIRECTIVES, {useValue: MyInhertLink, multi: true})]);

Here's a plnkr with an example working.

Solution 4

An achor should navigate to something, so I guess the behaviour is correct when it routes. If you need it to toggle something on the page it's more like a button? I use bootstrap so I can use this:

<button type="button" class="btn btn-link" (click)="doSomething()">My Link</button>

Solution 5

I am using this workaround with css:

/*** Angular 2 link without href ***/
a:not([href]){
    cursor: pointer; 
    -webkit-user-select: none; 
    -moz-user-select: none; 
    user-select: none
}

html

<a [routerLink]="/">My link</a>

Hope this helps

Share:
219,311

Related videos on Youtube

s.alem
Author by

s.alem

Apparently, I prefer to keep an air of mystery about me.

Updated on March 31, 2021

Comments

  • s.alem
    s.alem about 3 years

    In Angular 1.x I can do the following to create a link which does basically nothing:

    <a href="">My Link</a>
    

    But the same tag navigates to the app base in Angular 2. What is the equivalent of that in Angular 2?

    Edit: It looks like a bug in the Angular 2 Router and now there is an open issue on github about that.

    I am looking for an out of the box solution or a confirmation that there won't be any.

    • Sasxa
      Sasxa about 8 years
      You still can. It's just html. Any particular use for it?
    • s.alem
      s.alem about 8 years
      Yes, it is still valid html, but the effect is not the same with Angular 1.x.
    • Sasxa
      Sasxa about 8 years
      Did you try just <a>, without "html"?
    • s.alem
      s.alem about 8 years
      Yeah, but than the browser doesn't treat it in the same way. I know I can override i.e. the cursor effect with css, and assign pointer to all a tags. But that looks hacky.
    • Sasxa
      Sasxa about 8 years
      My opinion is that ng1 way was the wrong way (: Default behavior should be as it is in standard html...
    • Eric Martinez
      Eric Martinez about 8 years
      Totally agree with @Sasxa, to be honest that sounds like a useless "feature". Why would a framework hijack my html by default and not let it work as it should?
    • s.alem
      s.alem about 8 years
      I am not sure about how passive links to be handled but it is not a useless feature, at least for me. It is quite handy, for example, when you want to use a link to access controller.
    • lukiffer
      lukiffer almost 8 years
      @EricMartinez I think the issue here is less about whether or not Angular should hijack the default behavior, but rather that Angular's router requires the use of the <base> tag, so when you click on an <a href="#"> link rather than navigating to # you end up at /# or whatever your base href is. Interested to see how this pans out in the GitHub issue.
    • Sharifullah Sharif
      Sharifullah Sharif over 7 years
      I have the same problem i solved it with a([routerLink]=""). it is in pug which is equal to <a [routerLink]=""></a>
  • Pankaj Parkar
    Pankaj Parkar about 8 years
    @s.alem what ever you are saying, that having # inside anchor href can affect Angular1 route..may send you to default page(if its there)
  • s.alem
    s.alem about 8 years
    I know the effect of # in angular 1.x. I want a link that does nothing in angular2, just like href="" in angular 1.x.
  • Pankaj Parkar
    Pankaj Parkar about 8 years
    @s.alem so <a href="">My Link</a> will do that..but what happening currently with it?
  • s.alem
    s.alem about 8 years
    It navigates to the app base like I said in my edit.
  • s.alem
    s.alem about 8 years
    Yeah, that would be a solution, but looks hacky. I still feel like there should be an out of box solution like in angular 1.x.
  • s.alem
    s.alem about 8 years
    Upvote for a global, angular solution, but I'm not accepting it as the correct answer because as I said, I'm only looking for an out box solution, until they confirm there won't be any or until I really really need it. But still thank you very much.
  • Eric Martinez
    Eric Martinez about 8 years
    The problem with pointer-events is the lack of support with IE (caniuse) (I can bypass it even with IE11 weirdly enough), and it doesn't prevent to click the link from the console. I've upvoted @Pankaj answer because it's the easiest one from my point of view, my answer is just a way of doing it with angular2, I could make it easier but css selectors are limited.
  • xd6_
    xd6_ over 7 years
    This seems to break bootstrap tab links (such as <a href="#tab-id"> )
  • newman
    newman about 7 years
    I like this solution. If you want to have cursor to show a hand, add style="cursor: pointer".
  • Max
    Max about 7 years
    This notation can generate errors in the console, fyi. such as: XMLHttpRequest cannot load javascript:void(), Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.
  • Pankaj Parkar
    Pankaj Parkar about 7 years
    @John this seems to be causing because of some chrome extension.. I also had some issue with my application when my app was handling CORS, it was getting failed
  • Max
    Max about 7 years
    @PankajParkar Interesting, but it's an error reported by angular. We stepped away from using <a> elements without a valid href, too many problems with the Angular2 routers, instead, we use a <span> element with a link class and things work much better for us.
  • Pankaj Parkar
    Pankaj Parkar about 7 years
    Could you try to reproduce that error private window (as extension doesn't work there) It should work properly in that case..
  • Michael Kühnel
    Michael Kühnel almost 7 years
    You shouldn’t do that in the sense of sematic markup. Use a button Element in case you want to doSomething on the page.
  • Jun711
    Jun711 almost 7 years
    Which module is bootstrap function in?
  • Michael Kühnel
    Michael Kühnel over 6 years
    You can disable the href in a less hacky way using preventDefault like described here: stackoverflow.com/a/44465069/702783
  • Michael Kühnel
    Michael Kühnel over 6 years
    Why not use the anchor itself for preventing the default behavior? Like described here: stackoverflow.com/a/44465069/702783 Seems less »hacky« to me.
  • Irfan Raza
    Irfan Raza over 6 years
    This generates a href="#/" at DOM (angular 4)
  • Zymotik
    Zymotik over 6 years
    This worked [routerLink]="" it renders as <a href="null" (click)="myFunction()">My Link</a> Angular 5 in Chrome 64.
  • Zymotik
    Zymotik over 6 years
    I can confirm the same [routerLink]="" / href="null" is working in IE 11
  • Zymotik
    Zymotik over 6 years
    A content security policy may block this answer, try [routerLink]="". It will cause a href="null" to render.
  • narthur157
    narthur157 about 6 years
    [routerLink]="" will remove query params from your route, this is likely not what you want. You could use preserve query params, but this seems like going too far
  • Purple Piranha
    Purple Piranha almost 6 years
    This appears to be the simplest and most elegant solution.
  • Ian Poston Framer
    Ian Poston Framer over 5 years
    <a [routerLink]="" (click)="passTheSalt()">Click me</a> works in angular7. I see <a (click)="passTheSalt()">Click me</a> without routerLInk works in angular7 as well. what is better way to make a passive anchor link using [routerLink] or no routerLink?
  • Emiel Koning
    Emiel Koning over 5 years
    @IanPostonFramer When I remove [routerLink]="", the text Click me is not displayed as a link and does not show hand cursor icon.
  • yankee
    yankee about 5 years
    In many situations a good solution, however be aware that the button has bigger dimensions than just the text based anchor.
  • MrBoJangles
    MrBoJangles almost 5 years
    Why not just remove the href and replace it with nothing? We have CSS, so that negates the concern of the styles.
  • Paul Carlton
    Paul Carlton almost 5 years
    The second options does not work for me in AngularDart, using [routerLink]="" with (click)="navigateFunc(id)" will send me back to the root /. If pushing back I get the navigation url I wanted and then if I push back again I get to my original page. The browser goes to both urls basically.
  • Paul Carlton
    Paul Carlton almost 5 years
    However, option 1: href="javascript:void(0);" DOES work for me.
  • Ayyash
    Ayyash almost 5 years
    @yankee you can change that in css, but I don't recommend... fact is, a button is a button, and a link is a link... too sad the web is not that white or black.
  • ctaleck
    ctaleck over 4 years
    The accepted answer will reset the scroll position to the top, which may not be desirable in all situations.
  • Stavm
    Stavm over 4 years
    NOTICE: this will reset your URL params. buyer beware.
  • Drenai
    Drenai over 4 years
    <button> elements trigger click by default when the space key is pressed. Using span (or <a>) removes this feature - so keyboard actions won't work as expected
  • Admin
    Admin over 4 years
    This is a better solution as it's mainly a visual effect that's missing. You can put this CSS in the Angular project's top-level styles.css file and it will work great!
  • Kerry Johnson
    Kerry Johnson about 4 years
    What about when you Right-click → Open in New Tab? The fact that it actually tries to navigate to /null at that point makes me weary of this approach.
  • SUHAIL KC
    SUHAIL KC about 4 years
    Simple answer 👍
  • SUHAIL KC
    SUHAIL KC about 4 years
    Use <a href="" (click)="false">
  • runderworld
    runderworld almost 4 years
    yeah, i appreciate the solution but this breaks accessibility for many of us
  • andreivictor
    andreivictor over 3 years
    In Angular 11, it generates: <a href="(currentURL)">...</a>. On click, it won't trigger any route.
  • thenetimp
    thenetimp about 3 years
    just return false in the function, then you don't have to remember it in every tag you use the function.
  • thenetimp
    thenetimp about 3 years
    This is never the right solution. Spans are meant for formatting text, anchors for linking, and navigation, Accessibility tools handle these differently.
  • JoeCool-Avismón
    JoeCool-Avismón about 3 years
    This will go over updates and doesn't deal with routerlink or null values.
  • Sean
    Sean almost 2 years
    You might need to use routerLink="" rather than [routerLink]=""
  • Rak
    Rak almost 2 years
    [routerLink]="" works in angular 13 but it will not have hand cursor. How to fix this?