Angular UI-Router mais parâmetros opcionais em um estado

Como posso permitir parâmetros opcionais para minhas rotas sem usar uma string de consulta e usando apenas um nome de rota? No momento, estou especificando cada rota CINCO VEZES para permitir qualquer combinação de partes:

Todas as partes devem ser opcionais. A rota deve resolver qualquer variação.

.state("login", { url: "/login", templateUrl: "login.html", params: { a: null, b: null, c: null, d: null } }) .state("loginA", { url: "/login/:a", templateUrl: "login.html", params: { b: null, c: null, d: null } }) .state("loginAB", { url: "/login/:a/:b", templateUrl: "login.html", params: { c: null, d: null } }) .state("loginABC", { url: "/login/:a/:b/:c", templateUrl: "login.html", params: { d: null } }) .state("loginABCD", { url: "/login/:a/:b/:c/:d", templateUrl: "login.html" }) 

Deve haver um caminho mais fácil / limpo / menos feio.

Resposta curta….

 .state('login', { url: '/login/:a/:b/:c/:d', templateUrl: 'views/login.html', controller: 'LoginCtrl', params: { a: { squash: true, value: null }, b: { squash: true, value: null }, c: { squash: true, value: null }, d: { squash: true, value: null }, } }) 

Há um plunker de trabalho

A solução aqui poderia ser de dois tipos. O primeiro é realmente muito dynamic. O segundo está funcionando conforme necessário, um pouco mais rígido, mas aproveitando os resources internos do UI-Router de UI-Router do UI-Router .

I. abordagem dinâmica

Vamos observar o primeiro, que é interessante (mas talvez muito complicado em nosso cenário) . É muito parecido com este Q & A

Visualizações aninhadas do roteador ui recursivo

Tentamos resolver o URL que contém uma quantidade desconhecida de pastas * (diretórios) * nomes:

    

Estado poderia ser definido assim:

 .state('files', { url: '/files/{folderPath:[a-zA-Z0-9/]*}', templateUrl: 'tpl.files.html', ... 

E isso levará a uma pasta folderPath com o caminho completo da pasta.

Caso desejássemos resolver nosso cenário (lidar exatamente com três parâmetros) poderíamos estender coisas como essa

Controlador para manipulação de arquivos:

 .controller('FileCtrl', function($scope, a, b, c) { $scope.paramA = a; $scope.paramB = b; $scope.paramC = c; }) 

Definição de estado usando resolvedor:

 // helper method var findParams = function($stateParams, position) { var parts = $stateParams.folderPath.split('/') var result = parts.length >= position ? parts[position] : null; return result; } ... // state calls resolver to parse params and pass them into controller .state('files', { url: '/files/{folderPath:[a-zA-Z0-9/]*}', templateUrl: 'tpl.files.html', controller: 'FileCtrl', resolve: { a : ['$stateParams', function($stateParams) {return findParams($stateParams, 0)}], b : ['$stateParams', function($stateParams) {return findParams($stateParams, 1)}], c : ['$stateParams', function($stateParams) {return findParams($stateParams, 2)}], } }) 

II. params : {} recurso do roteador de interface do usuário params : {}

O segundo cenário, na verdade, é muito simples. Ele usa o recurso params : {} UI-Router : params : {} . Verifique sua documentação aqui:

http://angular-ui.github.io/ui-router/site/#/api/ui.router.state . $ stateProvider

Esta seria a nossa definição de estado:

 .state('login', { url: '/login/:a/:b/:c', templateUrl: 'tpl.login.html', controller: 'LoginCtrl', params: { a: {squash: true, value: null}, b: {squash: true, value: null}, c: {squash: true, value: null}, } }) 

E todos esses links funcionarão também:

     

E qual foi o truque:

squash{bool|string=} : squash configura como um valor de parâmetro padrão é representado na URL quando o valor do parâmetro atual é o mesmo que o valor padrão. Se squash não estiver definido, ele usa a política de squash padrão configurada.

Confira em ação aqui

Outra maneira simples de fazer isso é apenas definir um valor padrão para o parâmetro, assim:

 params: { thing1: "" } 

De acordo com os documentos do Angular UI Router , a configuração de um valor padrão automaticamente torna o parâmetro opcional.

Você pode passar parâmetros opcionais usando ui-sref . Você pode acessá-los em seu controlador usando o serviço $ stateParams. parameters que não são passados ​​simplesmente permanecerão nulos.

 .state("loginABCD", { url: "/login/:a/:b/:c/:d", templateUrl: "login.html" controller: function($stateParams) { console.log($stateParams.a + $stateParams.b); } })