简体   繁体   中英

AngularJS: Prevent page refresh when transitioning between routes

I had a problem previously where I wanted to prevent the page from refreshing when programmatically updating the URL.

I have a "home" view, eg: /books and I have specific views: eg: /books/123

The home page has a couple of side panels and a main panel with the list of books. When clicking on a book, I only want the main panel to update, leaving the rest of the page as it is, but I DO want to update the URL to reflect the book that is loaded. All books should be directly linkable, and so the URL reflects this direct link. I update the URL by setting $location.path() when a specific book is loaded, and I use reloadOnSearch:false in my ui-router state to prevent the refresh.

My routes are set up as follows:

.state('books', {
   url: '/books',
   title: 'Books',
   templateUrl: CONFIG.static_url + '/html/book.html',
   controller: 'BookCtrl'
})
.state('book', {
   url: '/books/:itemId',
   title: 'Books',
   templateUrl: CONFIG.static_url + '/html/book.html',
   controller: 'BookCtrl',
   reloadOnSearch: false
})

This works fine, but it has two problems.

1) When transitioning from the home "Books" page, to a specific book, the page IS refreshed. When transitioning from one specific book to another, the model updates without refreshing the page (which is the desired behaviour).

2) When using the browser back/forward controls, the change in URL is not reflected in the model and so the view doesn't update. However, it does work when transitioning to/from the home page to a specific page.

To fix problem 2, I have set a $watch on $location.path() so if it changes and it doesn't match with the model, I load in the correct item. This appears to work fine.

However, problem 1 remains. How can I seamlessly transition from the Home page, to a specific view, without the whole page refreshing while also retaining the browser back/forward functionality? I can probably continue to use the $watch functionality to update based on the URL, but I can't seem to get it to load without the page refresh.

  1. Make book a child of books and change its URL just to /:itemId .
  2. Do not manually set $location.path() , as this will force a refresh. Redirect between states using ui-sref directive or $state.go() function.

Try something like this:

.state('books', {
    url: '/books',
    // ... (template should contain <div ui-view></div> where sub-state content will be rendered)
})
.state('books.book', {
    url: '/:itemId',
    // ... (template and controller just for this sub-state; will get rendered into super-state's ui-view)
})

and link like this:

<a ui-sref="books.book({itemId:123})">Book 123</a>

You need to make the book as a child state of the books. By using that you achieve the required behavior as the book html will already be available for the route. I hope that will work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM