Angular: $locationProvider.html5Mode(true) routing issue - angularjs

I want to remove the # from my URLs, so I have the code below:
angular.module('building')
.config(['$stateProvider', '$locationProvider',
function ($stateProvider, $locationProvider) {
// Turn on #-less links.
$locationProvider.html5Mode(true);
$stateProvider
.state('building', {
url:'/building',
templateUrl: 'app/modules/building/building.html',
controller: 'BuildingQuery',
controllerAs: 'vm'
})
}]);
And I have <base href="/"> in my index.html file.
And the code works...sort of.
If I enter a link like this...
http://127.0.0.1:4000/#/building
Then the browser redirects that URL to...
http://127.0.0.1:4000/building
and loads the page.
However, if I enter this url...
http://127.0.0.1:4000/building
then...
Cannot GET /building
Because the # URLs redirect properly, I know $locationProvider.html5Mode(true); is doing something.
Any ideas? It might be useful to know that I'm using angm to generate the modules.

From the Angular docs:
Using [html5mode] requires URL rewriting on server side, basically you
have to rewrite all your links to entry point of your application
(e.g. index.html). Requiring a <base> tag is also important for this
case, as it allows Angular to differentiate between the part of the
url that is the application base and the path that should be handled
by the application.
I.e. you need to tell your server to rewrite any requests to /building to /index.html.

evsheino pointed me in the right direction. There's nothing wrong with my code, it was the server configuration causing problems. All I had to do was add the following to my gruntfile.js
middleware: function (connect, options) {
var optBase = (typeof options.base === 'string') ? [options.base] : options.base;
return [require('connect-modrewrite')(['!(\\..+)$ / [L]'])].concat(
optBase.map(function(path){ return connect.static(path); }));
},
keepalive: true,
port: 4000,
base: '.',
hostname: 'localhost',
debug: true,
livereload: true,
open: true
}
}
},
Full explanation can be found here: http://jjt.io/2013/11/16/angular-html5mode-using-yeoman-generator-angular/
EDIT: this was for connect

Related

Is there a way using angular ui router not show #!/login?

If I call $state.go('login') using Angular ui router, the suburl looks like this.
Is there a way to hide #!/login? It's first time to use angular ui router and I dont know even it's possible.
So I want to see only localhost:3000/
You can create a state without an url in ui-router, by simply not defining the url property when configuring your states.
Like this:
angular.module('app').config(function ($stateProvider) {
$stateProvider.state('login', {
component: 'loginComponent'
});
});
You wont be able to navigate directly to the login url. But you'll still be able to use ui-sref or $state.go('login') to navigate.
If you still want to be able to navigate directly to the login page, you can configure another login state in addition to the above, where you specify the url property.
angular.module('app').config(function ($stateProvider) {
$stateProvider.state('login', {
component: 'loginComponent'
}).state('loginDirect', {
url: '/login',
component: 'loginComponent'
});
});
Try this in your config file:
$locationProvider.hashPrefix('');
For e.g.
angular.module('myPageApp', ['ui.router'])
.config(function ($stateProvider, $locationProvider) {
$stateProvider
.state('app',{
url: '/app',
templateUrl: 'someView.html',
controller: 'appController'
})
...
$locationProvider.hashPrefix('');
});
In above code, you can omit # and ! signs but can't skip the routed state in the URL. You can get the URL as localhost:3000/login or you can set the route on '/' identifier.
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.
To make your HTML5 mode ON, try following code.
app.config(['$locationProvider', function($locationProvider) {
$locationProvider.hashPrefix(''); // by default '!'
$locationProvider.html5Mode(true);
}]);
Also in your header section of HTML, add this Base ref type as below:
<head>
...
<base href="/">
</head>
For more information, kindly refer this code application here: https://github.com/TheAjinkya/Angular-UI-Router
Hope its helpful!

angularjs cordova base href

trying to set the correct base href value for an angularjs html5 web app to work in cordova
initially using $locationProvider.html5Mode(true) with <base href="/">:
app works perfectly in a normal browser
cordova gives resource errors for css / js / templates etc
(I believe it looks for resources within the cordova root directory rather than the platform root?)
Tried a few alternatives are floated around here on SO and ui-router FAQs:
<base href="."> with html5 mode as per this answer :
assets are found ok in cordova (no resource errors)
ui-router goes into a tail-spin with infinite loop and the following error message
Error: Failed to execute 'pushState' on 'History': A history state object with URL 'https://page/' cannot be created in a document with origin https://example.com
<base href="./"> with html5 mode:
assets found in cordova (no resource errors)
gives me the dreaded Error: 10 $digest() iterations reached. Aborting! message
tried using frankwallis solution mentioned here but that didn't help (same error)
no base href with $locationProvider.html5Mode({enabled: true, requireBase: false});
assets found in cordova (no resource errors)
pages start loading inside themselves ?? ...like angular bootstraps twice in some states ?
my app config definition looks like:
myApp.config(['$locationProvider', '$urlRouterProvider', '$stateProvider', '$stickyStateProvider', function($locationProvider, $urlRouterProvider, $stateProvider, $stickyStateProvider) {
$locationProvider.html5Mode(true);
$stateProvider
.state('root', { // we define a 'root' state so that we can load some essential data prior to any template being loaded
url: '',
abstract: true,
sticky: true,
views: {
'root': {
template: '<ui-view/>',
}
}
})
.state('root.worldmap', {
url : '/worldmap',
templateUrl : 'templates/worldmap.tmpl.html'
})
.state('root.faq', {
url : '/faq',
templateUrl : 'templates/faq.tmpl.html'
})
.state("otherwise", {
url: "*path",
views: {
'root': {
template: "",
controller: ['$injector', function($injector) {
var $state = $injector.get("$state");
$state.go('root.worldmap');
}]
}
},
});
$stickyStateProvider.enableDebug(true);
}]);
For info:
using this method of alternative cordova deviceready vs angular.element bootstrap for cordova / browser respectively
OK so the way to get this working is by removing the base href AND disabling html5 mode :
[optional] create & checkout a new branch called dev-cordova or similar
this allows you to switch quickly between browser and device code
delete / comment the <base href="/"> in the main index.html
ensure that html5 mode is disabled in app.js by either
$locationProvider.html5Mode({
enabled: false,
requireBase: false
});
or
$locationProvider.html5Mode(false);
Don't forget to run cordova build ios (after you grunt / gulp etc to compile the js files)
...this ensures the files in the cordova /platforms/ios/www directory are updated.

$state.href with absolute: true doesn't return the right url

I'm using Angular and UI router. I'm trying to get a link shown on the page that the user can copy and share. This thread has shown me that $state.href is the function I'm looking for, however it isn't generating the correct link.
An important detail here is that the root of my application is not the root of the domain. In this case, the domain is localhost, but the root of the angular app is in localhost/dev/app/.
Here's the command I'm using inside my controller.
$scope.url = $state.href('survey', { survey: "asd" }, {absolute: true});
In my app.js, the following route is declared:
.state('survey', {
url: "/:survey/survey?ao",
templateUrl: "views/survey/survey.html",
controller: "surveyController",
},
data: {
requireLogin: false,
requireAdmin: false
}})
This should return http://localhost/dev/app/#/asd/survey, instead it returns http://localhost/#/asd/survey.
(The remarkable thing is that ui-sref="survey({survey: "asd"}) does translate to the correct link.)
Is there a way I can fix this so I get the full url?
Adding a base tag to my app page solved this issue for me. It defines the base URL for the page with the router references. For legacy support reasons, I'm on version 0.2.15 of Angular UI Router. I don't know if this is still necessary for more current versions.
<base href="http://localhost/dev/app/" />
.state('survey', {
url: "/:survey/survey?ao",
templateUrl: "views/survey/survey.html",
controller: "surveyController",
data: {
requireLogin: false,
requireAdmin: false
}
})
You had an extra '},' in after controller, maybe that is messing things up? Also if you're passing parameters you might want to include that as a params line:
params: {
survey: null
}
Also if you want the url http://localhost/dev/app/#/asd/survey your url should be:
url: "dev/app/:survey/asd/survey"

stateProvider using htm5Mode cannot GET error

I am using stateProvider with $locationProvider.html5Mode:
// Redirect any unmatched url
$urlRouterProvider.otherwise("/cool");
$stateProvider
// Dashboard
.state('cool', {
url: "/cool",
templateUrl: "views/cool.html"
});
$locationProvider.html5Mode(true);
But when I http://localhost:8080/cool I will get Cannot GET /cool error. http://localhost:8080/ and http://localhost:8080/#/cool is working correctly.
After some research I found out the problem is because of grunt connect. so I added modRoute to route all url to index.html:
livereload: {
options: {
open: true,
middleware: function (connect) {
return [
modRewrite([
'!\\.\\w+$ /'
]),
but now the problem is every url like http://localhost:8080/uncool to http://localhost:8080/cool.
First, make sure you have the "base"-tag in your head.
<base href="/">
Then make sure that your "/cool"-page serves the same thing as your "/". If not, the server will send back 404 (as expected). This has to be true for all your "sub pages".
To test if this is the case – create a link with a href to "/cool", angular should handle this "internally" with a pushState, which differs from just "browsing" to that page. Meaning, when you click the link, the page will serve as expected, but if you reload (CTRL + R), you will get the error.
If you use html5mode you have to include <base> tag in your head part in document. You can set requireBase to false and use html5mode without <base> tag. Please have a look at angular documentation and ui-router documentation

AngularJS issue with routeProvider and hashtag in url

I've some problem with my angular app, running on virtual host.
I'm use wamp with vhost settings: DocumentRoot "c:/sites/test.dev/www".
Have problem with ROUTES. I want, that my app page open like this:
http://test.dev/1 , where 1 = user_id.
This is my app.js:
$routeProvider
.when('/:id', {
templateUrl: 'views/user.html',
controller: 'UserController',
});
$locationProvider.html5Mode(true);
When i disable $locationProvider, all works fine, but hashtag "#" always appended to url, like http://test.dev/#/1 . Can anyone have some idea?
App folder /www/ with structure:
/controller/
/services/
/directives/
/views/
---/js/
---/css/
---user.html
app.js
index.html
Please try to use the following code:
$locationProvider.html5Mode({
enabled: true,
requireBase: false
});
It will work for you.

Resources