Angular route parameters contraints

让人想犯罪 __ 提交于 2019-12-06 09:19:09

问题


I'm coming from the Asp.net MVC world where route constraints are really useful. I'm currently developing an Angular JS SPA that incorporates client side routing.

I would also like to add parameter constraints to my client-side routes as in:

$.routeProvider.when("/post/:id/:name?")

where I'd like to constrain my :id parameter to only be valid when these are numbers.

I haven't found anything similar in Angular Docs (which are horrible to say the least). Can it be done? And maybe also parameter defaults?


回答1:


There's no built-in way to set route constraints, but you can do it pretty easily yourself by using the resolve feature.

module.config(function ($routeProvider) {
    $routeProvider.when('/post/:id/:name', {
        controller: 'PostCtrl',
        resolve: {
            id: function ($q, $route) {
                var deferred = $q.defer(),
                    id = parseInt($route.current.params.id, 10);

                if (!isNaN(id)) {
                    deferred.resolve(id);
                } else {
                    deferred.reject('Id is not a number');
                }

                return deferred.promise;
            },
            // This isn't really needed, you can extract the name using 
            // $routeParams.name as you usually would in the controller.
            name: function ($route) {
                return $route.current.params.name;
            }
        }
    });
});

By doing it this way you can inject id and name into PostCtrl:

module.controller('PostCtrl', function ($scope, $routeParams, id, name) {

});

id in this case will be a number. You can of course also use $routeParams.id and $routeParams.name but those are always strings.

In case something else than a number is passed, then the promise is rejected and you need to handle that, usually in the 'MainCtrl' or 'AppCtrl' if you're doing a SPA.

module.controller('AppCtrl', function ($scope, $log) {
    $scope.$on('$routeChangeError', function (ev, current, previous, rejection) {
        $log.error('Error changing route: ' + rejection);
        // Will print: Error changing route: Id is not a number
    });
});

Update

You can use resolve in combination with the $routeChangeError event to validate the route and redirect on error. The resolve properties are always run, even if they aren't injected in the controller.

resolve: {
    validation: function ($q, $route) {
        var deferred = $q.defer(),
            id = parseInt($route.current.params.id, 10);

        if (!isNaN(id)) {
            deferred.resolve();
        } else {
            deferred.reject('VALIDATION FAILED');
        }

        return deferred.promise;
    }
}

In your home controller simply add:

module.controller('AppCtrl', function ($scope, $location) {
    $scope.$on('$routeChangeError', function (ev, current, previous, rejection) {
        if (rejection === 'VALIDATION FAILED') {
            $location.path('/home');
        }
    });
});

This is a quite hacky way to solve it and you might be better of using ui-router (I haven't tried that one). Unfortunately it's not possible to listen to $routeChangeStart and abort if needed. Otherwise this could've been solved a lot nicer.




回答2:


Angular route source change - most transparent constraints

There's a pull request in AngularJS source (made by me) that adds regular expression constraints to route parameters. It works a simple as providing this kind of route definition:

/:parameter:regularexpression

An example would be

/profile/:id:[1-9]\\d*/edit

This means that id has to be a number not starting with a 0.

Additional requirements

There are of course some additional requirements to these parameters:

  1. parameter can't be optional or greedy - if it ends with ? or * this character will become part of regular expression (as these are both regular expression tokens with their respective meaning

  2. regular expression constraint can't use regular expression capture groups as ( and ) get escaped as part of regular expression constraint - this already works this way so if your parameter name includes ( or ) they will both be escaped

  3. regular expression constraint can't include / as these are route segment delimiters




回答3:


One way is to use ui-router, which allows to specify url using regex.



来源:https://stackoverflow.com/questions/21205937/angular-route-parameters-contraints

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!