UI Router: how to check the parameter to the state allows

I have a known list of supported values ​​for parameter A. I need to check the value of the status parameter before any of the status permissions are started, and if the value is invalid, to provide a supported value. My initial thought was to use the injection function to property the value of a parameter:

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

However, $stateParamsit is not used at this point (I was hoping for a preview version, like what you got in the solution), and it probably set the default value, not the value itself $stateParam. So I'm looking for something like urlRouterProvider.when $match.

My next idea was to just use urlRouterProvider.when. Boneless: To my horror, this works after the condition resolves.

My next idea was to capture the urlMatcherFactory encoding. The same deal (triggered after).

Update

Ugh! The problem is that the controller runs outside of the UI router through ngController. Moving inside should fix the sequence problem (and then whenshould work). Updated later today.

+4
source share
4 answers

MarcherFactory did the trick. After I fixed this ngController error and brought these controllers into the UI Router, it worked as I expected.

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

: :

+4

$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 $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'
      }
    }
  }
)

, deferred.reject(reason) https://docs.angularjs.org/api/ng/service/ $q - $stateChangeError $rootScope, - :

// test for failed routing access, redirect to index page
$rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) {
  if(__.isObject(error)) {
    switch(error.error) {
      case 'Access Denied':
        $state.go('index');
        break;
      case 'Invalid Value':
        console.warn('Invalid URL Params to State %o %o', toState.name, error);
        break;
    }
  }
});

Update , , . " , " - . ,

+2

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, , .

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
    });

Not sure if the controller can be replaced with onEnterin determining the status of the check, but it can be.

0
source

Source: https://habr.com/ru/post/1606042/


All Articles