Improve this Doc  View Source

ngHref

  1. - directive in module ng

Using Angular markup like {{hash}} in an href attribute will make the link go to the wrong URL if the user clicks it before Angular has a chance to replace the {{hash}} markup with its value. Until Angular replaces the markup the link will be broken and will most likely return a 404 error. The ngHref directive solves this problem.

The wrong way to write it:

<a href="http://www.gravatar.com/avatar/{{hash}}">link1</a>

The correct way to write it:

<a ng-href="http://www.gravatar.com/avatar/{{hash}}">link1</a>

Directive Info

Usage

Arguments

Param Type Details
ngHref template

any string which can contain {{}} markup.

Example

This example shows various combinations of href, ng-href and ng-click attributes in links and their different behaviors:

  Edit in Plunker
<input ng-model="value" /><br />
<a id="link-1" href ng-click="value = 1">link 1</a> (link, don't reload)<br />
<a id="link-2" href="" ng-click="value = 2">link 2</a> (link, don't reload)<br />
<a id="link-3" ng-href="/{{'123'}}">link 3</a> (link, reload!)<br />
<a id="link-4" href="" name="xx" ng-click="value = 4">anchor</a> (link, don't reload)<br />
<a id="link-5" name="xxx" ng-click="value = 5">anchor</a> (no link)<br />
<a id="link-6" ng-href="{{value}}">link</a> (link, change location)
it('should execute ng-click but not reload when href without value', function() {
  element(by.id('link-1')).click();
  expect(element(by.model('value')).getAttribute('value')).toEqual('1');
  expect(element(by.id('link-1')).getAttribute('href')).toBe('');
});

it('should execute ng-click but not reload when href empty string', function() {
  element(by.id('link-2')).click();
  expect(element(by.model('value')).getAttribute('value')).toEqual('2');
  expect(element(by.id('link-2')).getAttribute('href')).toBe('');
});

it('should execute ng-click and change url when ng-href specified', function() {
  expect(element(by.id('link-3')).getAttribute('href')).toMatch(/\/123$/);

  element(by.id('link-3')).click();

  // At this point, we navigate away from an Angular page, so we need
  // to use browser.driver to get the base webdriver.

  browser.wait(function() {
    return browser.driver.getCurrentUrl().then(function(url) {
      return url.match(/\/123$/);
    });
  }, 5000, 'page should navigate to /123');
});

it('should execute ng-click but not reload when href empty string and name specified', function() {
  element(by.id('link-4')).click();
  expect(element(by.model('value')).getAttribute('value')).toEqual('4');
  expect(element(by.id('link-4')).getAttribute('href')).toBe('');
});

it('should execute ng-click but not reload when no href but name specified', function() {
  element(by.id('link-5')).click();
  expect(element(by.model('value')).getAttribute('value')).toEqual('5');
  expect(element(by.id('link-5')).getAttribute('href')).toBe(null);
});

it('should only change url when only ng-href', function() {
  element(by.model('value')).clear();
  element(by.model('value')).sendKeys('6');
  expect(element(by.id('link-6')).getAttribute('href')).toMatch(/\/6$/);

  element(by.id('link-6')).click();

  // At this point, we navigate away from an Angular page, so we need
  // to use browser.driver to get the base webdriver.
  browser.wait(function() {
    return browser.driver.getCurrentUrl().then(function(url) {
      return url.match(/\/6$/);
    });
  }, 5000, 'page should navigate to /6');
});