Как реализовать псевдонимы путей в ui-router

Я пытаюсь найти способ реализовать псевдонимы маршрутов в Angular.js с помощью ui-router. Скажем, у меня есть состояние с url-статьей/: articleId, и я хочу, чтобы /article/some -article-title перенаправлялся (внутренне) в /article/ 76554 без изменения местоположения браузера. Это можно сделать с помощью ui-router?

Ответ 1

I. Отображение двойного состояния (повторное использование контроллера, просмотры)

ПРИМЕЧАНИЕ. Это оригинальный ответ, показывающий, как решить проблему с двумя состояниями. Ниже приведен другой подход, реагирующий на комментарий Geert

Существует plunker с рабочим примером. Скажем, у нас есть два объекта (на сервере)

var articles = [
  {ID: 1, Title : 'The cool one', Content : 'The content of the cool one',},
  {ID: 2, Title : 'The poor one', Content : 'The content of the poor one',},
];

И мы хотели бы использовать URL как

// by ID
../article/1
../article/2

// by Title
../article/The-cool-one
../article/The-poor-one

Затем мы можем создать эти определения состояний:

// the detail state with ID
.state('articles.detail', {
    url: "/{ID:[0-9]{1,8}}",
    templateUrl: 'article.tpl.html',
    resolve : {
      item : function(ArticleSvc, $stateParams) {

        return ArticleSvc.getById($stateParams.ID);
      },
    },
    controller:['$scope','$state','item',
      function ( $scope , $state , item){ 

        $scope.article = item;
    }],
  })

// the title state, expecting the Title to be passed
.state('articles.title', {
    url: "/{Title:[0-9a-zA-Z\-]*}",
    templateUrl: 'article.tpl.html',
    resolve : {
      item : function(ArticleSvc, $stateParams) {

        return ArticleSvc.getByTitle($stateParams.Title);
      },
    },
    controller:['$scope','$state','item',
      function ( $scope , $state , item){ 

        $scope.article = item;
    }],
  })

Как мы видим, фокус в том, что Контроллер и Шаблон (templateUrl) совпадают. Мы просто запрашиваем Сервис ArticleSvc getById() или getByTitle(). После решения мы можем работать с возвращенным элементом...

Плункер с более подробной информацией здесь

II. Алиасинг, основанный на встроенной функции UI-Router

Примечание. Это расширение реагирует на Geert соответствующий комментарий

Итак, существует встроенный/собственный способ UI-Router для псевдонимов маршрутов. Он называется

$urlRouterProvider -.when()

Я создал рабочий plunker здесь. Во-первых, нам понадобится только one состояние, но без каких-либо ограничений на идентификатор.

.state('articles.detail', {
    //url: "/{ID:[0-9]{1,8}}",
    url: "/{ID}",

Мы также должны реализовать некоторый mapper, преобразовывая заголовок в id (alias mapper). Это будет новый метод службы статьи:

var getIdByTitle = function(title){
   // some how get the ID for a Title
   ...
}

И теперь мощность $urlRouterProvider.when()

 $urlRouterProvider.when(/article\/[a-zA-Z\-]+/,
  function($match, $state, ArticleSvc) {

    // get the Title 
    var title = $match.input.split('article/')[1];
    // get some promise resolving that title
    // converting it into ID
    var promiseId = ArticleSvc.getIdByTitle(title);

    promiseId.then(function(id){

      // once ID is recieved... we can go to the detail
      $state.go('articles.detail', { ID: id}, {location: false}); 
    })

    // essential part! this will instruct UI-Router, 
    // that we did it... no need to resolve state anymore
    return true;
  }
);

Что это. Эта простая реализация пропускает ошибку, неправильное управление заголовком.... Но это, как ожидается, будет реализовано так или иначе... Проверьте его здесь в действии