Angularjs Normal Links with html5Mode - angularjs

I am working with angularjs in html 5 mode. Which appears to take control of all href's on the page. But what if I want to have a link to something within the same domain of the app but not actually in the app. An example would be a pdf.
If i do <a href="/pdfurl"> angular will just try to use the html5mode and use the route provider to determine which view should be loaded. But I actually want the browser to go to that page the normal way.
Is the only way to do this is to make a rule with the route provider and have that redirect to the correct page with window.location?

in HTML5 mode, there are three situations in which the A tag is not rewritten:
from the angular docs
Links that contain a target attribute. Example: link
Absolute links that point to a different domain Example: link
Links starting with '/' that lead to a different base path when base is defined Example: link
so your case would be 1. add target="_self"

As of Angular v1.3.0 there is a new rewriteLinks configuration option for the location provider. This switches "hijacking" all the links on the page off:
module.config(function ($locationProvider) {
$locationProvider.html5Mode({
enabled: true,
rewriteLinks: false
});
});
While disablig this behavior for all links may not be your intention, I'm posting this for others who, like me, want to use $location in html5 mode only to change the URL without affecting all links.

If you don't want Angular to take control of the href. Place a target attribute on the link.
So PDF will by pass the html5mode and the routeProvider and the browser will just go to that url.

Other solution. All links will work normally (reload page). Links marked by ng-href="/path" will play on pushState. Small JS hack help with it.
.config(["$locationProvider", function($locationProvider) {
// hack for html5Mode customization
$('a').each(function(){
$a = $(this);
if ($a.is('[target]') || $a.is('[ng-href]')){
} else {
$a.attr('target', '_self');
}
});
$locationProvider.html5Mode(true);
}])

Related

How to use angular ui router on "normal sites" without HTML5 mode?

In our team, we want to use angular-ui-router to assign a "state" by reading the url without hashbangs or html5mode, so that 1. We programmatically assign controllers based on "normal" urls and 2. We support ie9
We can't support hashbangs (which would give use ie9 support) because we are running this on a "non-spa website" and the urls are rendered server side. We literally just want to assign a state by reading a normal url on page load.
This seems trickier than I previously thought. Consider the following routes:
//Parent view
.state('abc', {
abstract: true,
controller: 'MainController'
})
//Search
.state('abc.Search', {
url: '/booking/search',
controller: 'SearchController'
})
Here is the goal: We want the whole path http://website.com/booking/search to pick up the state NOT http://website.com/#/booking/search, and we can't remove the # by adding html5mode.
If we try to add html5mode the page keeps refreshing in ie9 (we dont support ie8).
Now I know that we can remove state-routing and go back to adding ng-controller to the template, however we are in a unique position where we need to be able to programmatically assign controllers based on the url. This is the advantage on using angular-ui-state router.
Thanks in advance.

Angularjs: use config only for one controller

On one page I load content via ajax according to user picks (filters), to ensure that loaded content stays in place if user reloads or lands on the page, I put the picked filters into the url query string. Since I load the content via ajax on this particular page I don't need to reload the entire page every time a new filter is picked by the user, so I prevent browser to react on url change with the following config:
app.config(['$locationProvider', function($locationProvider) {
$locationProvider.html5Mode(true);
}]);
However this affects the entire app and prevents all other pages from reloading on url change, the behavior I don't want. How can I make this configuration to affect only one particular controller within my app?
If your goal is to prevent reloading the page when the query string changes, html5Mode is entirely the wrong tool for the job. You want reloadOnSearch: false which can be applied globally or to individual routes:
$routeProvider
.when('/foo', {
controller: 'fooCtrl',
templateUrl: 'foo.html',
reloadOnSearch: false
},
...
);
https://docs.angularjs.org/api/ngRoute/provider/$routeProvider
From Angular's documentation on $locationProvider, maybe the cause of that behavior is by design:
rewriteLinks - {boolean} - (default: true) When html5Mode is enabled,
enables/disables url rewriting for relative links.
If your app is reacting to the url to make a change as a sort of RESTful api I would recommend using ngRoute or even better uiRouter.
Hope that helps.
This is a tricky situation, and you might not like my suggestion; heck I don't even like this suggestion because it breaks the whole awesomeness of a single page application.
But what you could do, is to create a separate html file (lets call it pick-filters.html). On that new html file, have a new ng-app and therefore a separate app.js file for this particular page. In this new app.js file (lets call it pick-filters-app.js), you can use the app.config snippet that you have shown here. This should fix your problem of all pages not reloading because only pick-filters.html is referencing pick-filters-app.js which has this config snippet.

AngularJS $routeProvider otherwise catches my external redirections

I'm using $routeProvider in AngularJS with many routes configured. The "otherwise" section
is configured, so it redirects all the unknown routes to the main page of my application.
All I want is to redirect the browser from my controller to an external URL, but I cant.
I tried to use $window.location = external, window.location.href = external, but they doesnt work. The routing API redirects me to the default page set in otherwise every single time.
How could I achieve this with / or without major hacks. Unfortunately, It have to be done via JavaScript code from my controller.
Thanks in advance
That might not fully answer your question but to navigate outside of route scope you can use this
Links that contain target element
Example: link
Absolute links that go to a different domain
Example: link //this one might actually be of use for you
Links starting with '/' that lead to a different base path when base is defined
Example: link
AngularJS's routing is for routing within the page.
You should use native location.href for this.
Edit: can you give me a plunker for this? did you try something along this line yet?
$scope.path="http://www.google.com";
$scope.redirect = function(path){
location.href = path;
};
with
<button ng-click="redirect(path)">Go there</button>

AngularJS application links/routes in anchor tag with HTML5 mode

How do I link to other AngularJS application locations within an anchor A tag? I am using HTML5 hashless mode and would like to avoid having the page actually reload.
For example, in non-HTML5 mode I would do this:
<a href='#/path'>Link</a>
In HTML5 mode I can do this:
<a href='/path'>Link</a>
But this actually causes the browser to reload the new URL. I've also tried using ng-href and also the /#/path syntax but none of them seem to work as I'd like.
How do I properly link from an anchor tag?
Update:
It seems like this is possible without using $location, you just have to keep the same base link. From the docs:
When you use HTML5 history API mode, you will need different links in different browsers, but all you have to do is specify regular URL links, such as: link
When a user clicks on this link,
In a legacy browser, the URL changes to /index.html#!/some?foo=bar
In a modern browser, the URL changes to /some?foo=bar
In cases like the following, links are not rewritten; instead, the browser will perform a full page reload to the original link.
Links that contain target element. Example: link
Absolute links that go to a different domain. Example:
Links starting with '/' that lead to a different base path when base is defined. Example: link
Old:
You should use the $location service. Inject it into the controller and put it on the $scope (or in a convenience method):
function MainCtrl($scope,$location){
$scope.goto = function(path){
$location.path(path);
}
}
<a ng-click="goto('/path')">Link</a>
This worked for me in html5mode enabled.
<a ng-href='./path'>Link</a>
Angular Js uses hash prefix followed by exclaimation. Hence if you want to use the anchor tag then have it this way.
Link
https://docs.angularjs.org/tutorial/step_09

Relative links in AngularJS

In my templates I want to use relative routes. Currently I have absolute paths in my anchor href's, which is suboptimal
Settings
How can I rewrite this to be a relative navigation (in this relative to dashboard)?
It should work with hashbang and html5 history api routes (whichever AngularJS uses or falls back to)
Within your controller you can look at the $routeParams and build a base url to operate from.
From there your templates can operate against "{{baseUrl}}/relative/to/scope/baseUrl"
And urls built within your code can go to $scope.baseUrl + /relative/to/scope/baseUrl";
It's not exactly "relative" but it does solve the issue of allowing urls refining other urls without having to hard-code the hierarchy and worry about routeparams that are variables and such.
I'm not sure your angular version, but in my 1.2.18, when you set
<base href="/base"></base>
and whenever in your element href, you start with "relative/to/you/url", then your link will point to "/base/relative/to/you/url":
NOTE: I've turned on the html5 api mode for $locationProvider:
$locationProvider.html5Mode(true);
EDIT: See MDN document for <base> tag. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
I don't think you can rewrite it to use relative navigation. How is relative going to work if you want to link to /user/profile, but your user is on /dashboard/settings. If the main navigation links to simply profile (relative), it's going to go to /dashboard/profile, which I'm assuming is not what you want.
Why is relative pathing so important in your application? Anything more than savings keystrokes?
Old question, but I found this works:
$locationProvider.html5Mode({
enabled: true,
requireBase: false,
rewriteLinks: false
});

Resources