UI路由器动态URL匹配器

时间:2015-08-12 04:28:55

标签: angularjs angular-ui-router

使用UI路由器,有一种方法我只允许动态网址。

例如,我有一个服务MyData,其get方法使用$http。它返回一个条目列表。我想要做的是构造一个有效的入口ID数组,$ state url可以使用它来只允许那些。

var validArray = MyData.get().then(function(res) {
   var arr = _.chain(res).pluck('id').flatten().value();
   console.log(arr);
   // returns [12, 15, 20, 26];
}); 

我想要实现的只是允许通过$state网址访问这些数组项。

$stateProvider
   .state('entry', {
      abstract: true,
      url: '/entry/{id:int}', // is there a way to only allow those values from validArray?
      resolve: { //etc }
   })
   .state('entry.detail', {
      url: '/detail',
      // etc...
   });

2 个答案:

答案 0 :(得分:0)

我没有使用它,但可以在https://www.dropbox.com/developers/reference/oauthguide的ui-router api文档中找到与您需要的内容非常相似的内容。

它基本上允许您创建自定义路由参数约束,以便您的url: '/entry/{id:validIds} 条目看起来像:

var list = [12, 15, 20, 26];

$urlMatcherFactoryProvider.type('validIds', {
  encode: function(item) {
    // Represent the list item in the URL using its corresponding index
    return list.indexOf(item);
  },
  decode: function(item) {
    // Look up the list item by index
    return list[parseInt(item, 10)];
  },
  is: function(item) {
    // Ensure the item is valid by checking to see that it appears
    // in the list
    return list.indexOf(item) > -1;
  }
});

然后定义自定义网址匹配器

angular.config

这需要位于SELECT t1.Col1, t1.Col2 FROM t t1 JOIN t t2 ON t1.Col1 = t2.Col1 and t1.Col2 >= t2.Col2 Group by t1.Col1, t1.Col2 ORDER BY Count(t2.Col2), t1.Col1; 部分,因此您必须完成如何获取有效ID。

(注意,上面的代码是从链接文档中修改的,因此可能无法100%工作)

答案 1 :(得分:0)

a working plunker

在这种情况下,我会使用一个事件来检查id是否有效。这样我们就不仅可以使用$http .run() 阶段),但如果ID错误,我们可以更准确地决定该怎么做。所以我们有这些链接:

  <a ui-sref="entry({id:1})">
  <a ui-sref="entry({id:22})">
  <a ui-sref="entry({id:333})">
  <a ui-sref="entry({id:4444})">

这可能是我们带有支持ID的data.json:

{
  "allowedIds": [
    22, 333
  ]
}

通过此服务,我们可以检查是否允许id。它也会返回promise,以防$ http用于从服务器加载数据:

.factory('IdValidator', ['$http',
  function($http) {

    var allowedIds = null;

    // return bool or promise
    var  validate = function(id){

      if(allowedIds){
        return isValid(id);
      }

      return $http
        .get("data.json")
        .then(function(resp){
          allowedIds = resp.data.allowedIds;
          return isValid(id);
        })
    }
    // compare id with loaded allowed ids
    var isValid = function(id){
      return allowedIds.indexOf(id) >= 0;
    }

    return {
      validate : validate
    }

}]);

最后,我们需要对状态变化做出一些决定:

.run(['$rootScope', '$state', 'IdValidator',
  function($rootScope, $state, IdValidator) {

    $rootScope.$on('$stateChangeStart', function(event, to, params) {

      if (to.name !== "entry"){
        return;
      }

      var result = IdValidator.validate(params.id) ;

      // allowedIds loaded, we now that this id is OK
      if(result === true){
         return;
      }

      // now we have to stop exectuion any how
       event.preventDefault();  

      // result is false - id is not allowed
      if(result === false){

         $state.go("home");
         return;
      }

      // wait for a promise and try this state again
      result.then(function(isValid){

        $state.go(to.name, params);

      })

    });
}])

应该很清楚。如果结果是truefalse,我们可以采取行动..如果结果是承诺,我们只是等待其解决方案..然后再次重定向到此状态

通过这种方式,我们可以在整个应用程序生命周期内允许ID ...

检查here