48

In angularjs, I want to use button like this, but I still need the button looking.

<button href="#/new-page.html">New Page<button>

As a (link) does

<a href="#/new-page.html">New Page</a>

Is there a simpler way than this?

<button ng-click="newPage()">New Page<button>
$scope.newPage = function (){
    location.href = '#/new-page.html';
};

Note: Acutally, when I used to location.href for navigation, the whole is refreshed and the navigation is not under the control of angularjs. If I don't use link, how to navigate page in javascript code?

Do I need to create a custom directive to impl it?

Henry Leu
  • 2,184
  • 4
  • 22
  • 34

7 Answers7

66

Your ngClick is correct; you just need the right service. $location is what you're looking for. Check out the docs for the full details, but the solution to your specific question is this:

$location.path( '/new-page.html' );

The $location service will add the hash (#) if it's appropriate based on your current settings and ensure no page reload occurs.

You could also do something more flexible with a directive if you so chose:

.directive( 'goClick', function ( $location ) {
  return function ( scope, element, attrs ) {
    var path;

    attrs.$observe( 'goClick', function (val) {
      path = val;
    });

    element.bind( 'click', function () {
      scope.$apply( function () {
        $location.path( path );
      });
    });
  };
});

And then you could use it on anything:

<button go-click="/go/to/this">Click!</button>

There are many ways to improve this directive; it's merely to show what could be done. Here's a Plunker demonstrating it in action: http://plnkr.co/edit/870E3psx7NhsvJ4mNcd2?p=preview.

Josh David Miller
  • 120,525
  • 16
  • 127
  • 95
  • 47
    Why on earth isn't this built-in? – Kevin Mar 17 '14 at 23:58
  • the key for me was the tidbit above about the $location service adding in the # automatically. removing it from my new navigation path was the fix i needed. – icfantv Sep 02 '14 at 16:04
  • 1
    You don't need to $observer a string parameter. If it was an interpolation like `go-click={{path}}` then you'd $observe it. So the whole $observe block should be removed from your example. Just pass `attrs.goClick` to the $location and that's it – r.sendecky Apr 11 '15 at 09:06
  • @r.sendecky My intention was to support interpolation. The `$observe` will correctly handle both cases here. – Josh David Miller Apr 17 '15 at 20:36
  • 1
    I added `element.attr('href', 'javascript:');` to make link appears as a regular link – Alcalyn Sep 01 '16 at 10:46
27

With bootstrap you can use

<a href="#/new-page.html" class="btn btn-primary">
    Click
</a>
rtp
  • 794
  • 1
  • 10
  • 26
  • [Not a great choice for accessibility purposes](https://css-tricks.com/use-button-element/#aa-accessibility-concerns) – Wimateeka Jun 20 '22 at 19:01
21

If you're OK with littering your markup a bit, you could do it the easy way and just wrap your <button> with an anchor (<a>) link.

<a href="#/new-page.html"><button>New Page<button></a>

Also, there is nothing stopping you from styling an anchor link to look like a <button>


as pointed out in the comments by @tronman, this is not technically valid html5, but it should not cause any problems in practice

Community
  • 1
  • 1
Zach Lysobey
  • 14,959
  • 20
  • 95
  • 149
  • 5
    Unfortunately, nesting an anchor tag inside a button tag is not valid HTML5. http://stackoverflow.com/questions/6393827/can-i-nest-a-button-element-inside-an-a-using-html5 – tronman Jun 19 '15 at 15:50
  • 1
    @tronman thanks for pointing this out (though you probably meant to say "nesting a button inside an anchor..."). This option is not the cleanest, nor the best perhaps, but it *does* work, valid html5 or no. I've found you don't get much benefit from following the letter of the law with this kind of thing, and doubt browsers vendors will ever make it so stuff like this doesn't work however. – Zach Lysobey Jun 19 '15 at 17:24
  • Yes I got my tags switched. You're right... this will probably not break in the future. – tronman Jun 20 '15 at 18:53
  • This is the only solution that works for me as of ng `1.4.6`. Simply using `$location.path` will instantly go back to the page it came from, and there seems to be no good solution. – pdinklag Oct 02 '15 at 10:27
10

You can also register $location on the scope in the controller (to make it accessible from html)

angular.module(...).controller("...", function($location) {
  $scope.$location = $location;
  ...
});

and then go straight for the honey in your html:

<button ng-click="$location.path('#/new-page.html')">New Page<button>
jakarta
  • 121
  • 1
  • 6
9
 <a type="button" href="#/new-page.html" class="btn btn-lg btn-success" >New Page</a>

Simple...

Dave Ba
  • 107
  • 1
  • 1
2

For me, best solution is to use Angular router native directives with ui-sref like:

<button ui-sref="state.name">Go!!</button>

To understand that directive and get more options visit ui-router docs at:

https://ui-router.github.io/docs/0.3.1/#/api/ui.router.state.directive:ui-sref

: )

Ramon
  • 193
  • 1
  • 7
-1
<button type="button" href="location.href='#/nameOfState'">Title on button</button>

Even more simple... (note the single quotes around the address)

TJCC
  • 19
  • 5
  • That doesn't seem to do anything. Also button has no href. And I don't know, what the single quotes are supposed to achieve. – Jens Mander Mar 17 '19 at 10:42