Angular-ui.router: Update URL without view refresh

Simon H picture Simon H · Dec 14, 2014 · Viewed 20.6k times · Source

I have an Angular SPA that presents a variety of recommendation lists, and a Google Map of locations, based on different cuts of some restaurant data (see m.amsterdamfoodie.nl). I want each of these lists to have their own URL. In order for Google to crawl the different lists I use <a> tags for the offcanvas navigation.

At present the <a> tag causes a view refresh, which is very noticeable with the map.

  • I can prevent this using ng-click and $event.preventDefault() (see code snippets below), but then I need to implement a means of updating the browser URL.
  • But in trying Angular's $state or the browser's history.pushstate, I end up triggering state changes and the view refresh...!

My question is therefore how can I update a model and the URL, but without refreshing the view? (See also Angular/UI-Router - How Can I Update The URL Without Refreshing Everything?)

I have experimented with a lot of approaches and currently have this html

<a href="criteria/price/1" class="btn btn-default" ng-click="main.action($event)">Budget</a>

In the controller:

this.action = ($event) ->
    $event.preventDefault()
    params = $event.target.href.match(/criteria\/(.*)\/(.*)$/)

    # seems to cause a view refresh
    # history.pushState({}, "page 2", "criteria/"+params[1]+"/"+params[2]);

    # seems to cause a view refresh
    # $state.transitionTo 'criteria', {criteria:params[1], q:params[2]}, {inherit:false}

    updateModel(...)

And, what is I think is happening is that I am triggering the $stateProvider code:

angular.module 'afmnewApp'
.config ($stateProvider) ->
  $stateProvider
  .state 'main',
    url: '/'
    templateUrl: 'app/main/main.html'
    controller: 'MainCtrl'
    controllerAs: 'main'
  .state 'criteria',
    url: '/criteria/:criteria/:q'
    templateUrl: 'app/main/main.html'
    controller: 'MainCtrl'
    controllerAs: 'main'

One possible clue is that with the code below if I load e.g. http://afmnew.herokuapp.com/criteria/cuisine/italian then the view refreshes as you navigate, whereas if I load http://afmnew.herokuapp.com/ there are no refreshes, but no URL updates instead. I don't understand why that is happening at all.

Answer

John Bernardsson picture John Bernardsson · Jun 12, 2015

This is an example of the way to go if I understand correctly:

$state.go('my.state', {id:data.id}, {notify:false, reload:false});
//And to remove the id from the url:
$state.go('my.state', {id:undefined}, {notify:false, reload:false});

From user l-liava-l in the issue https://github.com/angular-ui/ui-router/issues/64

You can check the $state API here: http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$state