AngularJS: API: ng/directive/ngHref


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}}"/>

The correct way to write it:

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

Directive Info

  • This directive executes at priority level 99.

Usage

  • as attribute:
    <A
      ng-href="">
    ...
    </A>

Arguments

ParamTypeDetails
ngHreftemplate

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:

index.html
<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)
protractor.js
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');});

xit('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');});