How to use $stateprovider without # in URL?
If we use $locationprovider.html5mode(true) then first time it was loading correctly but after refreshing the page the state is not loading and error is displaying.
I will explain you the scenario. We are using ASP.NET web api as back end server and front end is purely HTML application with angular.JS . we are not facing any issues with backend server. we don't have issues with api calls. I will explain with a example: www.test.com/#/main/home is redirecting to www.test.com/main/home using $state.go and rendering the view perfectly. But after redirecting to www.test.com/main/home if we refresh the page we are getting 404 error. Please help out
I am looking for to provide URL as per use choice. So I need to eliminate the # for that.
The problem with html5mode(true) and page reload is that in HTML 5 mode the browser sends the full URL to the server when a page reload is triggered. And if the resource of the full URL does not exist on the server, an error is returned.
So to fix your problem, you need to add a rule on the server to always send the same .html file no matter what URL is called.
The $stateprovider will then initialize the client side state accordingly.
You need to re-write the url with .htaccess
Check this link out:
https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-configure-your-server-to-work-with-html5mode
Related
I was trying to remove '#' from URL.
I looked through a lot of example doing so. Almost all examples followed same 2 steps which I followed.
Step 1: Enable HTML5 mode
.config(function ($routeProvider,$locationProvider){
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl',
controllerAs: 'main'
})
.when('/products/',{
templateUrl:'views/HomeMain/products.html',
controller:'MainCtrl',
controllerAs:'main'
});
$locationProvider.html5Mode(true);
})
Step 2: Add basetag
<head>
<base href="/">
</head>
After following above mentioned steps I successfully removed '#' from the URL.
Whenever I navigate to 'products' page URL looks like http://localhost:9001/products/ which is exactly what I want.
But, whenever I reload products page, this error is displayed in the browser window:
Cannot GET /products/
Why am I receiving this error? How do I handle this error?
When using # you are browsing in client side and urls are never sent to server. However when you use html5Mode, you should also configure server side, to rewrite to urls and tell client will handle it
For asp.net see this
You had a URL like http://localhost:9001/#/products/ before enabling the HTML5 mode. Please note that the contents of the hash are never submitted to the server. So what was requested from the server was http://localhost:9001 only.
As soon as server returns response, and angular takes over the control, it sees the /products/ fragment of the hash, and reacts accordingly.
After enabling HTML5 mode, your URL becomes http://localhost:9001 for your home page. Then you visit the route for products, which makes your URL http://localhost:9001/products/. Please note that because HTML5 mode uses browser's history API, your page is not refreshed entirely, even if the URL (not the hash fragment) is changed.
Now, if you refresh your page, what server receives is http://localhost:9001/products/, and since this route is not handled on the server, it returns a 404 error.
For making this to work, you need to implement logic to return appropriate contents when this route is visited. For Node based apps, you can follow this answer.
This is because the web server receiving the request looks for a resource matching the full url on the server, which doesn't exist because the angular portion of the url refers to a route in your angular application and needs to be handled in the client browser.
You can do a URL Rewrite if using NodeJS/ExpressJS/IIS. Refer this blog for the solution:
http://jasonwatmore.com/post/2016/07/26/angularjs-enable-html5-mode-page-refresh-without-404-errors-in-nodejs-and-iis
I am working at a SPA using Flask(with jinja) and AngularJS. Everything works fine, but when the application is in a given state and I try to refresh the page in browser, the server responds with 404 response: "error": "Not found". Is there a way to make this work in a proper way when trying to access a page of the SPA application through the URL?
This may depend on how your dev http server is setup:
It should be set to always load the default page which is index.html such that the angular engine will load and run and only then it will serve the other routes (states) like localhost/state, otherwise the angular router would not be able to resolve the url since it is not loaded (letting the http server handle the request, serving a 404 Page Not Found)
The http servers sometimes serve only one level deep url's like localhost/state, not localhost/state/param and you need to change some settings to make it work, but I think this is beyond the scope of your question :)
You can use a hasher in SPA. You need to parse hash string before initializing view model and based upon the value of hash set your current visible page and then bind the view mode.
You need to have a rule to always return your SPA index.html page for any routes that match your angular routes. I'm not sure what your web server is, apache or nginx or whatever but you should be able to find instructions on how to match those requests back to index.html.
You must have enabled html5 mode to true in in your angular js app. Set that to false will solve your problem.
How do you get a server-side redirect to go to a certain view in an angular app? I am guessing it has something to do with the redirect not triggering the part after the hash, but can this limitation be beat?
More info
I'm redirecting from an MVC controller to a page with an angular app. I'm using ui-router. The page containing the ui-view gets rendered, but processing stops there. If I refresh twice or go to the URL manually the page works as expected.
The MVC controller is called from a form which posts a file to the server and asynchronously populates a database and redirects when it's finished.
I don't see the problem, you can send a full url with hash and all on the location header and the browser will follow it, just check the response headers for this:
http://web-cf8f140d-22d3-4acd-b7a5-f9fa4e15e094.runnablecodesnippets.com/
What you can't do is getting the hash part directly from the request on the server side.
I apologize this question turned out a bit long, but I have worked on this for some time and really needed to explain all the story.
Background: App based on MEAN stack, trying to authorize Facebook logins using Passport.js.
Following Passport.js guide I implemented something similar to:
// HTML
Add a Facebook login
// send to facebook to do the authentication
app.get('/connect/facebook',isLoggedIn, passport.authorize('facebook',
{ scope : 'email' })
);
// handle the callback after facebook has authorized the user
app.get('/connect/facebook/callback',
passport.authorize('facebook', {
successRedirect : '/profile',
failureRedirect : '/profile'
}));
Notice the target=_self in the html in order to skip Angular routing.
Clearly, authorization works fine. However, redirection does not work, as the routing is handled by Angular. After authorization I never land on /profile (but on the default Angular route).
Therefore, I tried with a custom callback as suggested by Passport.js here, with the hope of passing json data to Angular, and let Angular do the routing. I ended up doing something like:
// In the controller
$http.get("/connect/facebook").success(function(data){
// here I wait for json data from the server and do the routing
});
// I call this route from Angular
app.get('/connect/facebook',isLoggedIn,passport.authorize('facebook',
{ scope : 'email' })
);
// But Facebook lands here!
app.get('/connect/facebook/callback',function(req, res, next) {
passport.authorize('facebook', function(err, user, info) {
res.json({something:smtg});
...
Clearly custom callbacks work for local-login, as Passport.js explains. But here do you see the problem? I call /connect/facebook from Angular, but I should receive some json from /connect/facebook/callback.
I am about to give up Passport, but before this, do you see any solution which would allow landing on /profile after FB authorization, perhaps with a custom message? Many thanks for reading through.
EDIT:
The same question had been reported as an issue on the Passport-Facebook GitHub account. Some additional attempts have been posted there, but not quite the fix yet.
This is a bit more in depth than can be described in one answer, but I'll try to start pointing you in the right direction.
Essentially, Angular.js routes are not really HTML routes at all, but an internal route structure that happens to use the URL for use of the end user. Remember that Angular.js is a client script, and that a full page reload is not desired, as this will reload the entire script. Therefore, /# is used to trick the browser into jumping to a specific bit of code within the already loaded script. (as opposed to the traditional anchor location in the HTML document). Unfortunately (or fortunately), HTML 5 mode allows you to hide the /# part of the url, so instead of seeing http://somesite.com/#/someroute you just see http://somesite.com/someroute. Rest assured, however, that the /# is still there. Angular.js uses the HTML5 pushState (AKA HistoryAPI) to perform the magic replacement.
Given this, if you have called a server route, you are outside the Angular.js script, and any call to load the angular script again will start from the very beginning. You can't actually call your Angular.js route from the server without a full reload. Therefore, you are really doing a double route redirect here. Your server should be calling it's default route for angular, appending /#/someroute to the call. The angular.js page will load, parse off the /#, and redirect to the correct angular route. Keep in mind, however, that if there was any dependency on already loaded objects, those are no longer in memory. Therefore, any route accessed this way should operate as if it is an entry point to your application.
Effectively, you should try using successRedirect : '#/profile', keeping in mind that the profile route in angular should be treated as an app entry point.
Hopefully this gets you started.
If #Claies's way is not working, is it possible you have not get rid of the #= fragment from the facebook callback.
Have a read of this post
I was trying to preetify my URL in angular js app and remove the hash. What I did was added in line in my app.config function:
$locationProvider.html5Mode(true);
But this issues I am still facing are:
If I open a page like this $window.location.href = '#/sales'; the slash is encoded and page does not opens.
If I directly type in my browser localhost:9000/sales without hash the page does not opens.
Can someone please help.
To add to it, my base url is: http://localhost:9000
You should choose just one option: either you have hashes in the url, or not.
If hashes are ok - then just remove $locationProvider.html5Mode(true); from your code.
If you really want your app to work w/o hashes in the url then follow this (probably incomplete) checklist:
Remove # from any urls on your page
Configure your web-server to feed the same webapp on all requests which your webapp recognizes. I.e. If your webapp routing knows what to do when user agent is requesting /sales - then make sure that your web-server or backend platform you are using serves the page with your web-app