Set links to fallback to hashbang for older browsers - angularjs

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);
}

Related

Angular JS UI-Route Navigation

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

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 /

angularjs v1.3.15 deep linking / routing / path no longer working with hashtag (Migrated from v1.2.3)

I am very new to angular and working on some code that I wanted to upgrade the angular version from 1.2.3 to 1.3.15 (which I have also never done before). When I did, the navigation links on my index page stopped working; rather it seems like the router.js falls through to my $routeProvider.otherwise case and redirects to /home (you can see the refresh in my jumbotron). However, I also notice that when I click on the links, my url goes from localhost:8888/home to localhost:8888/home# or localhost:8888/home#home or localhost:8888/home#info, but the page routes don't work (the home page gets refreshed instead) - like the route is just appended to /home and it doesn't know what to do.
When I remove the deep linking ( hash / pound / # ) from the links in index.html, the code appears to work again, but I don't really understand why. It's highly likely I'm misunderstanding something in the breaking changes from 1.2 to 1.3, but the documentation made it seem like using # is still supported in 1.3.
By "upgrading" I replaced my angular.js, angular-resource.js, and angular-route.js in my project with their newer versions. I am using Apache karaf, and tested in both Chrome and Firefox with the same results.
Shortened code below:
Here is the index.html code that works in 1.2.3 and breaks in 1.3.15 (I used both # and #home to test if there would be a difference):
<div class="navbar navbar-inverse navbar-fixed-top">
...
My Project<small></small>
...
<div class="collapse navbar-collapse navHeaderCollapse" data-ng-controller="NavController">
<ul class="nav navbar-nav navbar-right">
<li class="{{navData['Home'].css}}">Home</li>
<li class="{{navData['Info'].css}}">Info</li>
</ul>
</div>
</div>
</div>
My router.js looks like:
angular.module("app").config(function ($routeProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$routeProvider.when('/home', {
templateUrl: "home.html",
controller: "HomeController",
isPublic: false
});
$routeProvider.when('/info', {
templateUrl: "info.html",
controller: "InfoController",
isPublic: false
});
$routeProvider.otherwise({ redirectTo: '/home' });
});
With 1.3.15, when I replace the hash / pound / # signs in index.html, with "/" for Home and "info" instead of the "#info", everything seems to work again.
I also tried upgrading potential dependencies to the following:
ui-bootstrap-tpls-0.13.0.js (was 0.6.0)
jquery-2.1.4.js (was 2.0.3)
I am using:
bootstrap.js (using 3.0.0)
I also have some additional libraries but didn't know if they are relevant to this. Let me know if I should add them to the list.
I attempted to simulate what I am seeing in plunker here: Angularjs v1.3.15 test # redirect
But the links appear to be working with the exception of when you click a link with just "#" as the href, the page template isn't loaded at all. So I don't know if the issue is related or completely different.
A few suggestions I've looked into (but maybe missed something):
I did see that people are upgrading ui-router, but I'm not currently using it; should I be? (Though plunker seems to be working with angular-route.js)
html5 is not playing nice in all arenas, but it appears configured in my code?
fixing the server to allow #, which I think is already done since the code used to work correctly
Thanks in advance for the help! If you could point me in the right direction that would also be appreciated!
The hash has a specific meaning in the HTML specification. It targets an element on a page. If you are on the page localhost:8888/home and click on the link localhost:8888/home#info the browser would jump to the element with the id info, if there was one. Consequently nothing happens if the element doesn't exist.
Angular intercepts clicks and url changes and allow you to change routes instead. To avoid any confusion (or unintentional behavior) Angular has two conventions. The first is using a prefix. It's optional and the one suggested is !. That's why this mode is also called the Hashbang mode, links to routes would start with #!.
The second, and more important one, is that routes start with /. So it's href="#/" and href="#/info". And this works no matter what version of Angular you are using. Of course, this fixes your plunker.
If you want to use hashes then don't activate the HTML5 mode.
One remark about your last point: The server doesn't care about #, since it only concerns the client.

Starting with single page apps

I am a beginner in Angularjs and I have downloaded the template "Angular Start" for angularjs.
It has come with some inbuilt files . Like homecontroller, AppjsFolder etc.
I wonder how I can start with the angularproject if I am with an empty Mvc Project? Moreover When I run the application, I am defaulted with this url in the browser: "http:/somelocalAddress/#/home" . Can anybody tell me how # is attached with the url as I can see the route.config file it does not have any.
I know there are some anchor tags in Layout.cshtml
<li data-ng-class="{active : activeViewPath==='/home'}"><a href='#/home'>Home</a></li>
<li data-ng-class="{active : activeViewPath==='/demo'}">Demo</li>
<li data-ng-class="{active : activeViewPath==='/angular'}"><a href='#/angular'>Learn Angular</a></li>
<li data-ng-class="{active : activeViewPath==='/about'}"><a href='#/about'>About</a></li>
<li data-ng-class="{active : activeViewPath==='/contact'}"><a href='#/contact'>Contact</a></li>
Here , the href of anchortags are attached with # and it makes a point that url gets # on clicking the anchor tag but when I run the application why there is /#/Home
Please guide me.
You are using Angular ngRoute module. Which is a full-ajax navigation controller. That means when you navigate through routes you are not actually going any where, ngRoute downloads partials htmls and renders them inside the div tagged with ng-view attribute creating a "fake" (but high-performance) navigation experience.
Angular uses # in order to avoid browsers load whole page every route change action. That's why the anchor in your code is using # as well.
Your code seems to be an extract of a menu, probably a bootstrap menu, and it wants to add 'active' class to the corresponding li section depending on the current path. The controller is probably using $location service in order to find out which is the current path using $location.path() method. When you call path() it returns the current path without '#' thus it isn't using it either in ng-class attribute.
By the way, you might activate $locationProvider's html5mode and do not use prefix # and simply your life ;). It uses the same technology, the problem is your audience will need to use a modern browser, but I'm pretty sure you use other dependencies that require so too, do you?
How to configure html5mode
angular.module('myApp',[
...
'ngRoute'
...
])
.config(function($routeProvider, $locationProvider){
$routeProvider
.when('/path/to/my/route')
.otherwise({
redirectTo: '/'
});
$locationProvider.html5Mode(true);
});

Resources