How to implement path aliases in ui-router

前端 未结 1 2105
我在风中等你
我在风中等你 2020-12-01 17:04

I\'m trying to find a way to implement route aliases in Angular.js using ui-router.

Let\'s say I have a state with the url article/:articleId

1条回答
  •  有刺的猬
    2020-12-01 17:22

    I. Doubled state mapping (reuse of controller, views)

    NOTE: This is original answer, showing how to solve the issue with two states. Below is another approach, reacting on the comment by Geert

    There is a plunker with working example. Say we have this two objects (on a server)

    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',},
    ];
    

    And we would like to use URL as

    // by ID
    ../article/1
    ../article/2
    
    // by Title
    ../article/The-cool-one
    ../article/The-poor-one
    

    Then we can create this state definitions:

    // 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;
        }],
      })
    

    As we can see, the trick is that the Controller and the Template (templateUrl) are the same. We just ask the Service ArticleSvc to getById() or getByTitle(). Once resolved, we can work with the returned item...

    The plunker with more details is here

    II. Aliasing, based on native UI-Router functionality

    Note: This extension reacts on Geert appropriate comment

    So, there is a UI-Router built-in/native way for route aliasing. It is called

    $urlRouterProvider - .when()

    I created working plunker here. Firstly, we will need only one state defintion, but without any restrictions on ID.

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

    We also have to implement some mapper, converting title to id (the alias mapper). That would be new Article service method:

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

    And now the power of $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;
      }
    );
    

    That's it. This simple implementation skips error, wrong title... handling. But that is expected to be implemented anyhow... Check it here in action

    0 讨论(0)
提交回复
热议问题