Paramètres d'itinéraire AngularJS avec n'importe quel caractère

Je suis nouveau chez AngularJS, pardonnez-moi si cela est évident, mais je cherche quelqu'un qui peut répondre à cette question délicate. Je suis en train d'implémenter une application et je dois passer quelques paramètres à une vue particulière pour afficher les détails d'un livre. Fondamentalement, je voudrais pouvoir utiliser les expressions de routage suivantes:

bookApp.config(['$routeProvider', function($routeProvider) { $routeProvider. when('/catalog', { templateUrl: 'cataloglist.htm', controller: 'catCtrl' }). when('/book/:title/:chapter', { template: 'chapterdetail.htm', controller: 'chapterCtrl' }). otherwise({ template: 'oops ... do not understand that route', }); }]); 

Le /book/:title/:chapter expression /book/:title/:chapter devrait me permettre de passer le nom du titre d'un livre. Je m'attends à pouvoir passer n'importe quel titre de n'importe quel livre. Pour s'assurer que les choses sont correctement délimitées, je vais coder l'URL de la valeur du titre, de sorte que, dans la valeur codée, il n'y aura pas de barres obliques et la valeur sera clairement délimitée par les caractères slash. C'est la façon normale de construire des URL qui contiennent des valeurs.

Le problème est qu'il existe des titres de livres qui contiennent le caractère slash (par exemple, The 3/5 solution ). C'est l'URL codée en tant que The+3%2F5+Solution . Ainsi, peut construire une URL comme ceci:

  /app/#/book/The+3%2F5+Solution/The%20Beginning 

Cependant, mon expérience semble montrer que toute la valeur est l'URL décodée AVANT que cela soit divisé en paramètres! Cela signifie que toute valeur de données avec une barre oblique dans celle-ci sera mal interprétée en tant que deux valeurs, et la correspondance de motif des paramètres d'itinéraire est interrompue, et seule la première moitié de la valeur est transmise. En outre, le chapitre peut avoir une barre oblique Dans le nom aussi.

Si j'étais en train de faire un service REST, j'aimerais que l'URL code la valeur, et l'URL sera analysée en morceaux avant que chaque pièce soit décodée. Par exemple, je peux utiliser les paramètres de requête dans une URL comme celle-ci:

 app.jsp?title=The+3%2F5+Solution&chapter=The%20Beginning 

Et cela fonctionnera correctement. En utilisant l'encodage d'URL, je peux passer n'importe quelle valeur de chaîne dans le titre. J'aurais attendu des paramètres d'itinéraire pour faire la même chose … mais j'ai déjà mentionné que je suis NOUVEAU à AngularJS.

Pour décoder le %2F dans une barre avant de déterminer les pièces, cela semble être un bug très grave. Apparemment, vous ne pouvez pas passer les valeurs avec une barre oblique en eux comme paramètres d'itinéraire. Est-ce que j'ai râté quelque chose? Quelle est la solution pour me permettre de passer en toute sécurité un nom de livre avec TOUT caractère possible (avec un titre de chapitre avec TOUT caractère), en tant que paramètre d'itinéraire?

En route.js un coup d'œil sur le code source de l'angular's route.js , il est décrit une possibilité d'atteindre ce que vous recherchez:

path peut contenir des groupes nommés commençant par deux points et se terminant par une étoile: par exemple :name* . Tous les caractères sont stockés avec impatience dans $routeParams sous le name donné lorsque l'itinéraire correspond.

Par exemple, les routes comme /color/:color/largecode/:largecode*\/edit correspondent /color/brown/largecode/code/with/slashes/edit et extraient:
color: brown
largecode: code/with/slashes .

Notez la barre oblique inverse à la fin de :largecode*\ param dans l'exemple. Il n'est pas présent dans la description des groupes nommés se terminant par une étoile, mais c'est là dans l'exemple. Je n'ai pas testé cela et je ne sais pas si cette barre oblique inverse est requise, alors prenez en compte que cela pourrait / ne serait peut-être pas nécessaire.

Ainsi, une solution à votre question ressemblera à: /book/:title*/chapter/:chapter*

Notez l'ajout /chapter/ partie. Il est nécessaire pour différencier les deux groupes nommés. Si vous utilisez simplement /book/:title*/:chapter* , tout tombera sous le nom :title* named group. Cependant, si vous utilisez /:title*/chapter/:chapter* , angular sait quand :title* named group ended: when it encounters /chapter/ in the route. Tout après le /chapter/ sera sous le :chapter* nommé groupe

Il semble que vous ne pouvez pas utiliser l'encodage d'URL en raison du comportement ci-dessus. Cela signifie que vous devez utiliser un encodage qui représentera le jeu de caractères Unicode complet sans jamais utiliser une barre oblique ou un signe de pourcentage ou un signe plus, ni rien d'autre qui pourrait amener le décodeur d'URL à penser qu'il y a une valeur codée là pour être décodée.

Le codage BASE 64 de la valeur fera le tour, et la solution semble être de définir les filtres suivants:

  bookApp.filter('btoa', function() { return function (str) { return window.btoa(encodeURIComponent(escape(str))); } }); bookApp.filter('atob', function() { return function(str) { return unescape(decodeURIComponent(window.atob(str))); } }); 

Cela vous permet d'écrire un code comme ceci:

 <a href="#/book/{{title | atob}}/{{chapter | atob}}">See Details</a> 

Ensuite, sur le côté récepteur, vous appelez Btoa pour que la valeur soit utilisée pour n'importe quel but. La valeur The 3/5 solution est ensuite codée en tant que VGhlJTI1MjAzJTJGNSUyNTIwc29sdXRpb24= qui sera toujours un seul paramètre dans le reconnaissanceur de motif de paramètre d'itinéraire, et est décodé exactement dans la valeur qui a été envoyée.

Prise en charge complète des langues. Un livre nommé 奥の細道 sera encodé sous JTI1dTU5NjUlMjV1MzA2RSUyNXU3RDMwJTI1dTkwNTM= – en évitant tout problème pouvant corrompre la valeur.

Les encodeURIComponent supplémentaires d' encodeURIComponent et d' escape sont encodeURIComponent à tromper le JS pour convertir la chaîne unicode en codage UTF-8, qui est ensuite transformé par la fonction window.atob, qui échouerait avec certains caractères Unicode de plus haut niveau. Plus d'informations sur Mozilla Developer Network