Angular JS UI-Route Navigation - angularjs

I'm trying to make a simple routing using UI-Route in Angular,but when I'm typing url in browser with # like this http://localhost:8080/#/stateone it adds some weird symbols to it like this http://localhost:8080/#!#%2Fstateone. Can anybody explain me what`s wrong with that?
Here`s my code in app.js file :
angular
.module('myApp', ["ngMaterial", "ui.router"])
.config(function($mdThemingProvider, $stateProvider) {
$mdThemingProvider.theme('default')
.primaryPalette('teal')
.accentPalette('orange');
$stateProvider
.state('stateone' , {
url: '/stateone',
template: '<h1>State One</h1>'
})
.state('statetwo', {
url: '/statetwo',
template: '<h1>State Two</h1>'
});
});
Template`s file code:
<ui-view></ui-view>

You can encode your urls in AngularJS and avoid the hash-bang from your overall app by enabling html5mode mode by adding this simple line in your config block of app.js
$locationProvider.html5Mode(true);
Reference link: AngularJS: how to enable $locationProvider.html5Mode with deeplinking

This problem could appear with the migration from version 1.5 to 1.6...
One of the most notable changes are:
Changing the default $location hash-prefix to '!', as the previous empty string default was unconventional and confusing.
the default hash-prefix used for $location hash-bang URLs has changed
from the empty string ('') to the bang ('!'). If your application does
not use HTML5 mode or is being run on browsers that do not support
HTML5 mode, and you have not specified your own hash-prefix then
client side URLs will now contain a ! prefix. For example, rather than
mydomain.com/#/a/b/c the URL will become mydomain.com/#!/a/b/c.
If you actually want to have no hash-prefix, then you can restore the previous behavior by adding a configuration block to you application:
appModule.config(['$locationProvider', function($locationProvider) {
$locationProvider.hashPrefix('');
}]);
Details

Related

AngularJS All slashes in URL changed to %2F

I'm having a massive problem with AngularJS routing.
Up until recently everything has been fine with the following route:
$routeProvider.when('/album/:albumId', {
controller: 'albumPageController',
templateUrl: 'views/album.html'
});
and using the href:
Link
However, now all of the slashes are being encoded into %2F.
So when I click the link, or type localhost:8000/#/album/1 into the browser, the URL is changed to:
http://localhost:8000/#%2Falbum%2F1
I've tried several things to correct this:
Using ng-href instead of href,
Not using the first / (ie href="#/album/{{album.id}}")
Running the app in Homestead localhost (Laravel's linux vagrant machine) instead of localhost on Windows 10
Any help would be much appreciated!
%2F is the percent-encoding for the forward-slash / character.
This problem is related to the fact that AngularJS 1.6 has changed the default for hash-bang urls in the $location service.
To revert to the previous behavior:
appModule.config(['$locationProvider', function($locationProvider) {
$locationProvider.hashPrefix('');
}]);
For more information, see SO: angularjs 1.6.0 (latest now) routes not working.
The most simple solution is to add a ! to client-side URLs (if not using HTML5 mode, which you probably do if you're here).
Client-side, update URLS like this:
#/foo/bar > #!/foo/bar
And since you keep the #, there is no issue of conflict with server-side routing. Everyone happy.
A bit late to the party but adding a '!' to your URLs will work just fine. This bothered me for a bit as well. This is a change in the latest AngularJS 1.6.x and I read somewhere that Google requires SPAs to have that '!' after the hash. As a result my routes look as they should but my navigation makes sure I add '!' in my references. For example:
<ul>
<li>Home</li>
<li>Page 2</li>
<li>Page 3</li>
<li>Page 4</li>
</ul>
I hope this helps you.
Regards!
For me, i fixed the problem :
app.config(function($locationProvider) {
$locationProvider.hashPrefix('');
$locationProvider.html5Mode({
enabled: false,
requireBase: true
});
});
<span>MyLink</span>
Which give : http://blablabla.co:8888/blabla#/mylink/
Hope this help.
slash encoding can be disabled:
$urlMatcherFactoryProvider.type('SlashFix', {
raw: true,
});
$stateProvider
.state('content',{
url: '/{slug:SlashFix}'
...
})
as described here https://www.coditty.com/code/angular-ui-router-replacing-slash-with-2f-quick-fix
Remove the hash symbol from the link, since you are using html5mode you do not need a hash symbol for routing
Link
becomes
Link

$routeProvider.when('/', ...) has no effect, when html5 mode is on

Solution to the problem: url you write in base tag should have a trailing slash.
I have the following routes configuration, but template is not requested, if html5 mode is on. No errors, no attempts to get the resource from the server.
Neither changing base url, nor setting prefix with hasPrefix('!') has no effect on this behavior
angular
.module('beneficiaryBanks')
.config(configRoutes);
configRoutes.$inject = ['$routeProvider','$locationProvider'];
function configRoutes($routeProvider, $locationProvider) {
$routeProvider
.when('/',
{
controller: 'beneficiaryBanksListController',
controllerAs: 'listVM',
templateUrl: 'BeneficiaryBanksList.cshtml'
});
$locationProvider.html5Mode(true);
}
It looks like angular does not match current url with '/'.
update 1
Debugging shows that for url http://localhost:8080/APS/Home/BeneficiaryBanksModule and base address APS/Home/BeneficiaryBanksModule angular sees route as /BeneficiaryBanksModule which does not match with /, whereas route becomes just a / when html5 mode is disabled.
As I could see here, there are some configurations that you may have to do in order to achieve this combination of AngularJS and IIS Express with html5 mode activated.
I don't know if you read this article, but there are a few tips to make it work.
That's because your request is handled by server itself, but not by your angular app.
Try to read some articles about how to setup your server to work with html5 mode:
https://dzone.com/articles/fixing-html5mode-and-angular
http://www.thinkovator.com/blog/post/angularjs-html5-mode-and-iis-rewrite/
Hope, it will help.
The problem was in base tag. If it does not end with slash / angular treats last part as a file name and drops it.
That's why I saw /BeneficiaryBanksModule instead of /

ui routing without urlRouterProvider.otherwise

Routing doesn't occur if I don't include $urlRouterProvider.otherwise('/'); in the config.
my go app engine setting with gorilla is
r := mux.NewRouter()
r.HandleFunc(/admin, handleAdmin)
and angularjs config is;
angular.module('admin')
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider.state('home', {
url: '/',
templateUrl: '/admin/index.html',
controller: 'AdminController as admin'
});
//$urlRouterProvider.otherwise('/');
})
when I don't call $urlRouterProvider.othwerwise line, and I open http://localhost:8080/admin I expect to see admin/index.html, but I don't. I see it only if I navigate to http://localhost:8080/admin#/ manually.
But if I add $urlRouterProvider.othwerwise option and go to http://localhost:8080/admin it redirects automatically to http://localhost:8080/admin#/
I don't think this is usual way to do it because I may want "otherwise" to route to a custom 404 page. What point do I miss?
By default, Angular adds the hashPrefix in front of urls. So when you navigate to http://localhost:8080/admin , You don't see index.html since you have not yet visited the url as defined in the angular's ui-router. You will have to navigate to http://localhost:8080/admin/#/ to actuall be in the / state of your application.
It is the same reason that your app doesn't work without the .otherwise(), since then it automatically redirects you to the / state later.
For a possible fix:
Inside your .config function:
// This is in your app module config.
$locationProvider.html5Mode(true);
And in your index.html:
// This is in your index.html head.
<base href="/" />
The problem is not with not having a declared otherwise.
The problem lays on your route. You're specifying the url to be '/', that means the state home is accessible only through http://localhost:8080/admin/ and NOT through http://localhost:8080/admin
What the otherwise does is. When you access the url http://localhost:8080/admin the router try to find a state that matches the url, but don't find it. So it redirects to http://localhost:8080/admin/ which matches with your home state.

Set links to fallback to hashbang for older browsers

I'm setting HTML5 mode on. And thus, links in template are written without hashbang like:
<a ng-href='/link/to/action'>Click here</a>
But problem is, older IE versions need the hashbang urls and I know that angularjs will fallback for IE to hashbang.But I'm already forming the links according to HTML5. How to fallback my own links to hashbangs?
In other words,
I want my links in the template to reflect the mode (HTML5 or hashbang) type and set its href accordingly.
So, for older browsers, I want the link to be like this instead:
<a ng-href='/#/link/to/action'>Click here</a>
$locationProvider.html5Mode(false);
Add this to you app.config function, it will disable the html5 mode, and enable hash #
if you need ! also then add this too
$locationProvider.hashPrefix('!');
Ex:
angular.module('yourApp', ['ngCookies', 'ngResource'])
.config(function($stateProvider, $urlRouterProvider, $locationProvider){
$locationProvider.html5Mode(false);
$locationProvider.hashPrefix('!');
})
EDIT: For checking html5 you can include the modernizer.js library, or use the code samples they provide
Here are some techniques you can use to find a browser supports Html5 or not
http://diveintohtml5.info/detect.html#geolocation
Ex:
if (Modernizr.geolocation) {
$locationProvider.html5Mode(true);
} else {
$locationProvider.html5Mode(false);
}

Problems with AngularJS $location.path

I am having fun and games with a troublesome AngularJS route, so lets see if I can explain this as well as I can.
APP.JS:
app = angular.module("index", []);
app.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/booking/damage/:regnumber', {
templateUrl: 'damage',
controller: 'DamageCtrl'
}).
otherwise({
redirectTo: '/'
});
}
]);
app.controller('IndexCtrl', function($scope, $location) {
$scope.regnumber = '';
$scope.progress = function() {
if ($scope.regnumber !== '') {
$location.path('/booking#/damage/' + $scope.regnumber);
} else {
$location.path('/booking#/damage');
}
};
});
My initial page has a path of
http://localhost/windscreens/glass/index#/index
and within this page is a form that via ng-submit="progress() calls the $scope.progress function within my IndexCtrl controller. There is a field in the form of ng-model="regnumber".
So when filling in the input field with lets say "ABC" and clicking on the button, I'd expect the path to become:
http://localhost/windscreens/glass/booking#/damage/ABC
But it becomes
http://localhost/windscreens/glass/index#/booking%23/damage/ABC
Thing is I am still really becoming used to the Angular routing system and haven't quite got it yet. Any advice on this will be appreciated!
Why am I seeing what I am seeing? What have I got wrong here?
The Angular $routeProvider can only change the part of the URL after the hash (#), so when calling $location.path(), you just use a plain URL fragment like you defined in the route for DamageCtrl.
Some explanation
I'm going to simplify a bit here, but hopefully it will help you understand what's going on.
You're making a SPA (single-page app), so the URL you enter in your browser to get into your app doesn't change while you navigate between routes; by default $routingProvider appends #/whatever/route to that base URL. In your case it looks like you have your entry point (ng-app) in a file called /windscreens/glass/index, so all routes will get appended to that.
Because you don't have an /index route defined that we can see, I'm not sure how http://localhost/windscreens/glass/index#/index is working for you. It should send you to http://localhost/windscreens/glass/index#/ because your otherwise route is just /.
Back to the question
If I understand your question correctly, I would make the index file (where ng-app lives) /windscreens/glass/index.html, then you can just enter http://localhost/windscreens/glass/ to get into the app, because the webserver will serve the contents of index.html by default.
At that point, your index page URL would become http://localhost/windscreens/glass/#/, and your /booking/damage/ routes would be http://localhost/windscreens/glass/#/booking/damage/ABC etc. The code to navigate to them would then be
$location.path('/booking/damage');
Angular routing changes the route on the page; it doesn't take you to a new directory or page.
So if index.html contains your Angular app and you have routes for "booking", "reservation", "cancellations", etc. You'll end up with urls that look like:
/glass/index.html#/booking
/glass/index.html#/reservation
/glass/index.html#/cancellations
The route merely appends itself to the index.html.
So, in a sense, your routes are working correctly. The %23 that you see being added is the url encoded # sign.
If you have a second Angular app that is found at /glass/booking and you're trying to forward the user to it, you can use $window.location.hash and $window.location.pathname. For example,
$window.location.hash = "/damage/ABC";
$window.location.pathname = "/windscreens/glass/booking";
should take you to:
/windscreens/glass/booking#/damage/ABC

Resources