UI路由器:如何在状态解析之前验证参数

时间:2015-09-05 08:56:23

标签: angularjs validation angular-ui-router

我已经获得了参数A支持值的已知列表。我需要在触发任何状态结果之前验证状态参数的值,如果该值无效,提供支持的价值。我最初的想法是为参数的value属性使用可注入函数:

params: {
  A: {
    value: [
      '$stateParams',
      'validator',
      function validateParamA($stateParams, validator) {
        // return some value
      }
    }
  }
}

但是,$stateParams此时未填充(我希望预览版本与解析中的内容类似),并且这可能会设置默认值,而不是{{1本身。所以我正在寻找类似$stateParam' urlRouterProvider.when的内容。

我的下一个想法就是使用$match。没有骰子:令我沮丧的是,在状态解决之后,这会引发

我的下一个想法是劫持urlMatcherFactory的编码。同样的交易(火灾之后)。

更新

唉!问题是控制器正在通过urlRouterProvider.when在UI路由器外部执行。将其移到内部应该修复序列问题(然后ngController应该工作)。将在今天晚些时候更新。

4 个答案:

答案 0 :(得分:4)

MarcherFactory做了这个伎俩。在我纠正了ngController废话并将这些控制器带到UI路由器之后,它就像我预期的那样工作。

// url: '/{locale:locale}'

function validateLocale(validator, CONSTANTS, value) {
    var match = validator(value);

    if (match === true) {
        return value;
    }

    if (match) { // partial match
        newLocale = match;
    } else {
        newLocale = CONSTANTS.defaultLocale;
    }

    return newLocale;
}

$urlMatcherFactoryProvider.type(
    'locale',
    {
        pattern: ROUTING.localeRegex
    },
    [
        // …
        function localeFactory(validator, CONSTANTS) {
            return {
                encode: validateLocale.bind({}, validator, CONSTANTS)
            };
        }
    ]
);

:愤怒:

答案 1 :(得分:2)

我最近遇到了同样的问题,并通过解析回调中的sed调用解决了这个问题。我有一些日历视图的默认参数,并希望事先验证参数。没有在这个主题上找到任何其他内容,但它似乎是一个非常可靠的解决方案。这是我的样本状态:

$q.defer()

如内联评论中所述,您可以将简单字符串或整个对象传递到$stateProvider.state( 'tasks.list', { url : '/:type?month&year&dueDate', // optional params for filtering params : { type : { value : 'all' // all|open|assigned|my }, month : { value : 1, // current month, needs a callback, no static value type : 'int' }, year : { value : 2016, // current year, needs a callback, no static value type : 'int' }, dueDate : { value : undefined, // 'no default value' - parses 2016-04-23 to da js date object type : 'date' } }, resolve : { validParams : ['$q', '$stateParams', function($q, $stateParams) { var deferred = $q.defer(); var allowedTypes = ['all', 'open', 'assigned', 'my']; if (allowedTypes.indexOf($stateParams.type.trim().toLowerCase()) < 0) { // deferred.reject(reason) also takes a simple string or nothing, you can use this information on UI.Router's $stateChangeError Event deferred.reject({ error : 'Invalid Value', param : 'type', value : $stateParams.type }); } if ($stateParams.month < 1 || $stateParams.month > 12) { deferred.reject({ error : 'Invalid Value', param : 'month', value : $stateParams.month }); } if ($stateParams.year < 2014 || $stateParams.year > 2099) { deferred.reject({ error : 'Invalid Value', param : 'year', value : $stateParams.month }); } // if a _deferred object was already rejected, it can't be resolved anymore, so this doesn't hurt at all deferred.resolve('Valid Values'); return _deferred.promise; }], taskListModel : ['TaskHttpService', '$stateParams', function(TaskHttpService, $stateParams) { // no matter if 'validParams' is resolved or not, this is called - so you might want to validate again or do some other check if you make an ajax call return TaskHttpService.loadTasks({ month : $stateParams.month, year : $stateParams.year, dueDate : $stateParams.dueDate }); }] }, views : { menu : { templateUrl : '/menu.html', controller : 'MenuController' }, body : { templateUrl : '/body.html', controller : 'BodyController' } } } ) https://docs.angularjs.org/api/ng/service/ $ q - 您可能希望收听deferred.reject(reason)上的$stateChangeError对信息做任何事情:

$rootScope

更新 完成答案后,我发现您在之前要求验证已调用已解析的参数。在标题中你说“在州解决之前” - 所以如果拒绝承诺,国家就不会得到解决。也许这可以帮助你了

答案 2 :(得分:1)

如果在状态结算中解析A并且其他结果依赖于它,您将能够检查$ stateParams并在需要时提供替代值。其他决议将在A。

之后解决
$stateProvider
    .state('state', {
        resolve: {
            A: ['$stateParams', 'validator', function($stateParams, validator) {
                return validator.validate($stateParams.A) ? $stateParams.A : 'default';
            }],
            otherResolve: ['A', function(A) {
               ///
            }
        }
    });

其他结果不应该直接使用$ stateParams,我不知道你是否有问题。

答案 3 :(得分:0)

如何将状态分成两部分:一部分进行验证,另一部分是实际的目标状态。

$stateProvider
    .state('validationState', {
        // The controller below will not get instantiated without defining template
        template: '',
        controller: function ($stateParams, $state) {
            if (/* your validation */) {
                $state.go('targetState', /* simply forward the valid parameter */);
            } else {
                $state.go('targetState', /* provide your valid parameter value */);
            }
        }
    })
    .state('targetState', {
        // whatever you want to resolve, yadda yadda
    });

不确定控制器是否可以在验证状态定义中用onEnter替换,但可能。