Angular state provider not displaying full URL - angularjs

I just inherited an application where there are several ui-sref="portal.main.content" in the code.
What I'm confused about is, to navigate to this state, we need to enter /#/portal/main/content.
However it is rendered on the page without the #. So it will work when clicking on the page, however it won't work if I try to open into a new tab as that page doesn't exist. What am I missing here?

The problem comes from the fact that your application is served from a server environment that deals with urls as if they were real paths for real resources on the server file system. Therefore, when your are in a single page, it's not reloaded when you navigate to another state url, because ui-router handle this internally, consequently doesn't produce 404 or 403 errors, but when you load a page first time, it's required from the server and gives you 404 and 403 errors because the resource you're looking for doesn't exists or is forbidden.
What you have to do is to configure your server side environment to target the index.html page when your are not refering to a file (like css and js files), so all url will end up in the index.html page with an url to be handled by the ui-router. Each server side technology (Apache, IIS, node.js, etc) will have a different way to handle this, but mostly have a URL Rewrite module and similar ways to handle this.
Also, if it's not a problem by using the hash like url, you can disable html5Mode to prevent ui-router to do such thing. You can achieve this by injecting $locationProvider on your .config and disabling it like so: $locationProvider.html5Mode(false);
For example:
angular.module('myApp', ['ui.router'])
.config(function ($stateProvider, $locationProvider) {
$stateProvider
.state('home', {
url: '',
templateUrl: 'views/home.html',
controller: 'HomeCtrl'
})
.state('about', {
url: '/about',
templateUrl: 'views/about.html',
controller: 'aboutCtrl'
});
$locationProvider.html5Mode(false);
});

Related

Can the ionic function "ion-nav-view" (ui-router) work with ngRoute?

I am trying to merge the Angularfire-Seed with a sample Ionic App. This has worked so far quite well.
To browse between my views, I am interested to use the ionic functionality:
// requires ui-router
<ion-nav-view></ion-nav-view>
instead of
// requires ngRoute
<div ng-view></div>
The problem is that the ion-nav-view (Ionic) is part of the ui-router (see here explanation) whereas ng-view part of ngRoute (Angularfire-seed).
Is there therefore a way to keep using the ngRoute (as a lot of coding has been done in the Angularfire-Seed project and thus I dont want to switch to ui-router), but still use ion-nav-view?
Follow-up: has someone implemented AngularFire with Ionic (and thus ui-router)? Available git?
No, ion-nav-view uses the ui-router under the hood. Unless you want to write your own implementation you can't use ngRoute with it.
EDIT
To answer your question about using your linked file with Ionic, you'll have to refactor it to use ui-router. Check the UI Router Guide here and the Ionic docs here. It's well worth reading the first link to get a thorough understanding.
Dependencies
ui-router is included in the Ionic bundle so you don't need to explicitly state it as a dependency.
So provided you already have Ionic as a dependency, instead of
angular.module('myApp.routes', ['ngRoute', 'simpleLogin'])
you can just have
angular.module('myApp.routes', ['simpleLogin'])
.config blocks
I've not used ngRoute but the syntax between the $stateProvider of ui-router look quite similar. With ngRoute you used the $routeProvider like so...
.config(function($routeProvider, $locationProvider) {
$routeProvider
.when('/chat', {
templateUrl: 'partials/chat.html',
controller: 'ChatCtrl',
})
With ui-router configuring a 'state' is something like the following (the use of $urlRouterProvider.otherwise() at the end catches any URLs that haven't been explicitly defined and redirects to whichever URL you specify)
.config(function($stateProvider, $urlRouterProvider){
$stateProvider
.state('home', {
url: '/',
templateUrl: "partials/home.html",
controller: 'HomeCtrl',
resolve: {
// resolve stuff in here, check the docs for implementation differences
}
})
.state('chat', {
url: '/chat',
templateUrl: "partials/chat.html",
controller: 'ChatCtrl',
}
})
$urlRouterProvider.otherwise('/');
Authentication is handled in your linked file, this link may help angular ui-router login authentication. Good luck!

Angular UI Router not matching URL path

When I go to localhost:3000/login, I'm redirected to localhost:3000/login#/login. How is that happening? I'm using the 1.3 release of AngularJS if that matters.
(function() {
this.app.config([
'$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/login');
$stateProvider.state('register', {
url: '/register',
templateUrl: '/components/user/register.html',
controller: 'UserCtrl'
}).state('login', {
url: '/login',
templateUrl: '/assets/components/auth/login.html',
controller: 'AuthCtrl'
});
}
]);
}).call(this);
The reason you are seeing localhost:3000/login#/login is because your $stateProvider configuration uses the .otherwise route which goes to #/login. The first /login is part of your URL path to the endpoint that retrieves the HTML for your Single Page Application (SPA) - it is part of your base URL.
For developers first starting out with SPAs, it might appear counter-intuitive that "navigation" in the app doesn't actually change the URL path - and thus endpoints of the server. Because of that there are no HTTP requests or HTTP-302 redirects. The app (or Angular, in this case) only changes the fragment (#) portion of the URL - that is how $stateProvider or $routeProvider "navigation" works.
So, the routes you configure in SPA determine "logically" which view to show. While the content of the view could load from an external URL, it is not related to the "route" definition itself.
Determine where your SPA will live. Determine what belongs to your SPA and what doesn't - and would be serviced by a different endpoint. Within SPA, "navigate" via #/path/to/view-style routes. Change url via $location.path to navigate outside of your SPA to a different endpoint.
== Same endpoint / different "routes" - all part of the same App:
baseurl.com/basePath#/about
baseurl.com/basePath#/login
baseurl.com/basePath#/product/153
== Different endpoints - different apps. Each one is an HTTP request to the server:
baseurl.com/basePath/about
baseurl.com/basePath/login
baseurl.com/basePath/product/153/
EDIT:
It is possible to use /page-view/other/params without #, turns out. Take a look at the following SO question.
In short, it's called HTML5 mode, and it can be configured with $locationProvider:
$locationProvider.html5Mode(true);
This however requires a bit more configuration and also more configuration on the server: https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-configure-your-server-to-work-with-html5mode

html5Mode with base tag does not work on refresh

AngularJS - html5Mode - Cannot GET /login
So I have seen this post and my problem is very similar. I have used base tag to get my relative urls to work. And I have $locationProvider.html5Mode(true); in my application. Everything seems to work fine to keep /#/ urls out of the application, but when the user refreshes the browser it says page not found. The url it is going to is where my router should be pointing to:
$routeProvider
.when('/', {
templateUrl: 'views/coverPage.html',
controller: 'MainCtrl'
})
.when('/coverPage', {
templateUrl: 'views/coverPage.html',
controller: 'MainCtrl'
})
This is just an example of my router page. Again, this works when I link through a button, but when I load the url: http://www.someurl.com/somepath/coverPage it says page not found.
If it works fine, when navigating from a link but get a page not found when you refresh it appears to be a server side issue.
Be sure to acutally load the right angular app from the server at the specified url. You need a kind of wildcard url matching for the server side route. But without knowing more details of your application I can only guess.

AngularJS routed page refresh never loads

I'm trying to use AngularJS in a salesforce local hybrid android app, and while a simple test of the angular code works in firefox, when I run it in the Android emulator it loads for a fraction of a second and is replaced with a blank screen.
I've noticed that refreshing the page after routing ( going to [URL]/index.html#/ after the first page load ) ends up with an eternal 'ajax loading' spinner. I suspect this might be the root of my problem. My routing code looks like this:
var contactlistModule = angular.module("AugmentedContactList", ['ngRoute']);
contactlistModule.controller(ContactlistController);
contactlistModule.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/', {
controller: 'ContactlistController',
templateUrl: 'viewparts/contactlistview.html'
}).when('/contact', {
controller: 'ContactController',
templateUrl: 'viewparts/contact.html'
}).otherwise({
redirectTo: '/'
});
}]);
Why does this refreshing error happen? Shouldn't going to index.html have the same effect as index.html#/ ?
I guess going to index.html without enabling html5Mode won't work as you expect.
You can enable it by injecting $locationProvider and adding this line to your config:
$locationProvider.html5Mode(true);
However, be aware that to enable html5 mode you will need to configure your server to return index.html (or whatever your main page is) on every URL request.
See also:
$locationProvider docs

AngularJS: how to enable $locationProvider.html5Mode with deeplinking

When enabling the html5Mode in AngularJS via $locationProvider.html5Mode(true), navigation seems to be skewed when you land on a page deeper in the site.
for example:
http://www.site.com
when i navigate to the root, i can click all links in the site, Angular's $routeProvider will take over navigating through the site and loading the correct views.
http://www.site.com/news/archive
but when i navigate to this url (or hit refresh when I'm on a deeplink like the above one...) this navigation is not working as I expect it to.
first of all, our as the Documentation for $locationProvider.html5Mode specifies, we catch all urls on the server, similar to the otherwise route in angular, and return the same html as the root domain. But if I then check the $location object from within the run function of angular, it tells me that http://www.site.com is my host and that /archive is my path. the $routeProvider arrives in the .otherwise() clause, since i only have /news/archive as a valid route. and the app does weird stuff.
Maybe the rewriting on the server needs to be done differently, or I need to specify stuff in angular, but currently i'm clueless as to why angular see's the path without the /news segment included.
example main.js:
// Create an application module
var App = angular.module('App', []);
App.config(['$routeProvider', '$locationProvider', function AppConfig($routeProvider, $locationProvider) {
$routeProvider
.when(
'/', {
redirectTo: '/home'
})
.when('/home', {
templateUrl: 'templates/home.html'
})
.when('/login', {
templateUrl: 'templates/login.html'
})
.when('/news', {
templateUrl: 'templates/news.html'
})
.when('/news/archive', {
templateUrl: 'templates/newsarchive.html'
})
// removed other routes ... *snip
.otherwise({
redirectTo: '/home'
}
);
// enable html5Mode for pushstate ('#'-less URLs)
$locationProvider.html5Mode(true);
$locationProvider.hashPrefix('!');
}]);
// Initialize the application
App.run(['$location', function AppRun($location) {
debugger; // -->> here i debug the $location object to see what angular see's as URL
}]);
Edit
as per request, more details on the server side:
the server side is organised by the routing of zend framework, and it handles it's own routes (for serving data to the frontend on specific /api urls, and at the end, there is a catch-all route if no specific other route is bound, it serves the same html as the root-route.
so it basically serves the homepage html on that deeplinked route.
Update 2
after looking into the problem we noticed this routing works fine as it is, on Angular 1.0.7 stable, but shows the above described behaviour in the Angular 1.1.5 unstable.
I've checked the change-logs but haven't found anything useful so far, I guess we can either submit it as a bug, or unwanted behaviour linked to a certain change they did, or just wait and see if it get's fixed in the later to be released stable version.
Found out that there's no bug there.
Just add:
<base href="/" />
to your <head />.
This was the best solution I found after more time than I care to admit. Basically, add target="_self" to each link that you need to insure a page reload.
http://blog.panjiesw.com/posts/2013/09/angularjs-normal-links-with-html5mode/
This problem was due to the use of AngularJS 1.1.5 (which was unstable, and obviously had some bug or different implementation of the routing than it was in 1.0.7)
turning it back to 1.0.7 solved the problem instantly.
have tried the 1.2.0rc1 version, but have not finished testing as I had to rewrite some of the router functionality since they took it out of the core.
anyway, this problem is fixed when using AngularJS vs 1.0.7.
Configure AngularJS
$location / switching between html5 and hashbang mode / link rewriting
Configure your server:
https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#wiki-how-to-configure-your-server-to-work-with-html5mode
My problem solved with these :
1- Add this to your head :
<base href="/" />
2- Use this in app.config
$locationProvider.html5Mode(true);

Resources