6

I use ui-router.
Here are my nested states:

$stateProvider
.state('books', {
  abstract: true,
  url: '/books',
  controller: 'BooksCtrl',
  templateUrl: 'contents/books.html'
})
.state('books.top', {
  url: '/top',
  templateUrl: 'contents/books-top.html'
})
.state('books.new', {
  url: '/new',
  templateUrl: 'contents/books-new.html'
});

How can I set books.new state to be default child of the books abstract state, so then when you hit /books ui-router redirects to /books/new?

laser
  • 1,388
  • 13
  • 14
Michael
  • 15,386
  • 36
  • 94
  • 143

2 Answers2

8

There is a working example

We can use built in features. 1) default is such child state which has empty url:

$stateProvider
    .state('books', {
      abstract: true,
      url: '/books/new',
      controller: 'BooksCtrl',
      ..
    })
    .state('books.new', {
      //url: '/new',
      url: '',
      ...
    })
    .state('books.top', {
      url: '^/books/top',
      ...
    });

And 2) to keep /books in place, we can use redirection

  $urlRouterProvider.when('/books', '/books/new');

And these links will work as expected:

// href
<a href="#/books">
<a href="#/books/new">
<a href="#/books/top">
//ui-sref
<a ui-sref="books.top">
<a ui-sref="books.new">

Check it here

Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
1

Try this way:

$stateProvider
.state('books', {
  abstract: true,
  url: '/books',
  controller: 'BooksCtrl',
  templateUrl: 'contents/books.html'
})
.state('books.top', {
  url: '/top',
  templateUrl: 'contents/books-top.html'
})
.state('books.new', {
  url: '',
  templateUrl: 'contents/books-new.html'
});

EDIT: I know that's not very nice, but you can create additional state with same arguments except url:

var booksArgs = {
  url: '',
  templateUrl: 'contents/books-new.html'
};
$stateProvider.state('books.new', booksArgs);
$stateProvider.state('books.new_', angular.extend({}, booksArgs, {
    url: '/new'
}));

Another solution from this post:

In states configuration:

$stateProvider
.state('books', {
  url: '/books',
  controller: 'BooksCtrl',
  templateUrl: 'contents/books.html',
  redirectTo: '.new'
})
.state('books.top', {
  url: '/top',
  templateUrl: 'contents/books-top.html'
})
.state('books.new', {
  url: '/new',
  templateUrl: 'contents/books-new.html'
});

On module run:

app.run(['$rootScope', '$state', function($rootScope, $state) {
    $rootScope.$on('$stateChangeStart', function(evt, to, params) {
      if (to.redirectTo) {
        evt.preventDefault();
        $state.go(to.redirectTo, params, { relative: to });
      }
    });
}]);
Community
  • 1
  • 1
karaxuna
  • 26,752
  • 13
  • 82
  • 117
  • if I follow your solution, I'll get `/books` URL for the **new books** page. I need it to be `/books/new` and also be accessible through `/books`. – Michael Oct 09 '15 at 11:05
  • I am not use how will this work and as you said, it's not very nice. I'll try one thing, if it works I'll let you know – Michael Oct 09 '15 at 11:22
  • @MikeVayvala See [this solution](http://stackoverflow.com/a/29491412/1265753) too – karaxuna Oct 09 '15 at 11:24
  • @MikeVayvala made redirection relative, I think it will be more useful in multiple nested states. Did not test, hope it works – karaxuna Oct 09 '15 at 11:37