Angular ui-router with url request parameter containing dot

In our Angular application, we have to deal with an identifier containing a period. For example:

book = { id: '123.456' } 

We have problems using an identifier such as URL parameters. Everything works well if navigation occurs through "Angular", namely clicking on the link that calls $state.go('bookDetails', {bookId: book.id}); . But when reloading the page, everything does not work.

"Cannot GET / bookDetails? BookId = 123.456"

in the controller:

 $scope.viewBookDetails = function() { $state.go('bookDetails', {bookId: book.id}); } 

in view

 <a href="" ng-click="viewBookDetails(); $event.stopPropagation();"> 

in the router:

 .state('bookDetails', { url: '/bookDetails?bookId' } 

in browser:

 https://example.com/bookDetails?bookId=123.456 

The link works if the "dot" is replaced with %2E in the browser.

We tried to replace "dot" with "% 2E" in the parameter for $ state.go ()

 $scope.viewBookDetails = function() { $state.go('bookDetails', {bookId: book.id.split('.').join('%2E')}); } 

but it doesn’t work, because "%" is automatically encoded, and the "dot" in the browser is replaced with "% 252E"

 https://example.com/bookDetails?bookId=123%252E456 
+7
angularjs urlencode angular-ui-router query-parameters
source share
3 answers

The update issue that I received with the url request parameter containing a period is a server issue.
This is due to the way I communicate with html5mode (redirecting to index.html if it is not a static resource) in the grunt server settings

 // The original grunt server settings connect: { options: { port: 9000, // Change this to '0.0.0.0' to access the server from outside. hostname: 'localhost', livereload: 35729 }, livereload: { options: { open: true, middleware: function (connect) { return [ require('connect-modrewrite')(['^[^\\.]*$ /index.html [L]']), //Matches everything that does not contain a '.' (period) and causes the problem connect.static('.tmp'), connect().use( '/bower_components', connect.static('./bower_components') ), connect().use( '/app/styles', connect.static('./app/styles') ), connect.static(appConfig.app) ]; } } }, 

I changed

 require('connect-modrewrite')(['^[^\\.]*$ /index.html [L]']), 

to

 require('connect-modrewrite')([ '!\\.html|\\.js|\\.css|\\.svg|\\.jp(e?)g|\\.png|\\.gif|\\.ttf$ /index.html' ]), 
+5
source share

If you use connect-history-api-fallback on your server (e.g. lite-server ), dotted URLs are not rewritten by default.

connect-history-api-fallback code

 if (parsedUrl.pathname.indexOf('.') !== -1) { logger( 'Not rewriting', req.method, req.url, 'because the path includes a dot (.) character.' ); return next(); } 

Starting with connect-history-api-fallback version 1.2.0, dotted URLs are allowed , and you can solve this problem using aa rewrite roule

Example

If your URL with a dot /api/test/:id (for example, /api/test/123.34 ) and you are angular is an application on the index.html page, you can add a rewrite rule in connect-history-api-fallback like this

 rewrites: [ { from: /^\/api\/test\/[0-9]+\.[0-9]+$/, to: 'index.html' } } ] 
+2
source share

I have completely revised the code. I can use dots, so please unlock the plunker to show where you get the error message.

http://plnkr.co/edit/Ct09Q9uoc282JuWdsO1s?p=preview

 console.log("Scripts loading... "); // Here a skeleton app. Fork this plunk, or create your own from scratch. var app = angular.module('demonstrateissue', ['ui.router']); app.controller('myController', function($scope, $state){ $scope.book = { id: '123.456' }; $scope.viewBookDetails = function() { console.log('new id'); $state.go('bookDetails', {bookId: 456.3456}); } }); // Empty config block. Define your example states here. app.config(function($stateProvider, $urlRouterProvider, $urlMatcherFactoryProvider) { $stateProvider.state('bookDetails', { url: '/bookDetails:bookId', controller: function($scope, $stateParams) { $scope.book = { id: $stateParams.bookId }; }, template: "<h3>book: {{book}}</h3>" }); $urlRouterProvider.otherwise("/bookDetails/91.23"); }); // Adds state change hooks; logs to console. app.run(function($rootScope, $state, $location) { $rootScope.$state = $state; $rootScope.$location = $location; function message(to, toP, from, fromP) { return from.name + angular.toJson(fromP) + " -> " + to.name + angular.toJson(toP); } $rootScope.$on("$stateChangeStart", function(evt, to, toP, from, fromP) { console.log("Start: " + message(to, toP, from, fromP)); }); $rootScope.$on("$stateChangeSuccess", function(evt, to, toP, from, fromP) { console.log("Success: " + message(to, toP, from, fromP)); }); $rootScope.$on("$stateChangeError", function(evt, to, toP, from, fromP, err) { console.log("Error: " + message(to, toP, from, fromP), err); }); }); 
 body { margin-top: 6em; } .link { text-decoration: underline; color: blue; } .link:hover { cursor: pointer; } .header { position: fixed; right: 0; top: 0; height: 6em; width: 100%; border-bottom: 1px solid gray; } 
 <!DOCTYPE html> <html> <head> <script src="https://code.angularjs.org/1.2.25/angular.js"></script> <script src="https://rawgit.com/angular-ui/ui-router/0.2.13/release/angular-ui-router.js"></script> <script src="main.js"></script> <link rel="stylesheet" href="styles.css" /> <title>Plunk demonstrating ui-router issue</title> </head> <body ng-app="demonstrateissue"> <div ui-view>ui-view not populated</div> <div class="header"> Current URL: <b>{{$location.url() }}</b> <br> Current State: <b>{{$state.current.name }}</b> <br> Current Params: <b>{{$state.params | json }}</b><br> </div> <br/> <br/> <div ng-controller="myController"> {{book}} <br/> <a ui-sref="bookDetails({bookId: 6789.1011})">Change params to book with dot</a><br/> <button ng-click="viewBookDetails()">View Book Details</button> </div> </body> </html> 
+1
source share

All Articles