Best way to set up 404 pages in a angular SPA? - angularjs

I have an application running on angular and I already have an http intercept setup. My issue is that my api returns some 404 errors that I would want to redirect to a 404 page and some that I wouldn't. For example when navigating to a new page, if the content of that page returns a 404 I want to direct to a 404 page instead of loading an empty template. However on a page where a user is checking out (paying for a purchased item) I check to see if they have a credit card token stored on file. If they do we can offer them the choice to use it. If they don't have one on file the api returns a 404 and we ask them to enter one.
My issue is that because of these two cases, it's not as simple at calling $state.go('404') anytime a 404 is thrown. I'm weighing a few options. One, have the api return a special message if it should redirect to a 404. This seems less than ideal, not really the responsibility of the api and we have multiple clients on a shared api. I could try to detect the current state/page in the http intercept and create a list of states that should redirect. I could $rootScope.$broadcast('no-template-data') or something similar from each controller that needs this and redirect from an global app.run function.
Has anyone else faced this challenge with single page applications?

Related

upon refreshing of the browser, the URLs containing 'hypen' is not going through angular $routeProvider .when(), but directly requesting the server

I am using MEAN Stack, and jade for html templating for developing a project. Since I am using jade all the .when() of the $routeProvider goes through the server and then rendered. Things are absolutely fine until recently I added $httpProvider.interceptor for authenticating each request. Basically, I started using JWT token based authentication and before requesting anything to the server, in my interceptor I am attaching 'Authorization' header. And the first middleware for protected apis I am verifying the token present in the 'Authorization' header. If present then proceed, else send authorization error.
Now, as mentioned in the title of the question. I have a few URLs containing hypen(-) between two words just to increase the readability.
eg: .when('/firstPart/secondPart1-secondPart2/thrirdPart', {
templateUrl: '/path/to/file'
})
this url is working fine if user going through the normal flow of getting to this url. The problem arises when the user comes to this page and hits the browser's refresh button, as he gets an error 'Authorization header not set'
I did a few research on what and why this is happening, I found the answer in
AngularJS not intercepting direct requests from Address Bar. According, to this answer and few other I understood that on refreshing browser makes a direct request to the server and doesn't go through angular routes, and thus, interceptor that is attaching the Authorization header to each request header is not getting called.
As, suggested by the same link, the workaround is that if auth verification fails make a call to '/', I donnot wish to do that as the user has just refreshed the page and he has to ideally get back the same page as he was in before he pressed refreshed. I am stuck here on how to do this.
Also, there is another mind–boggling this is if, I remove the 'hyphen'(-), and make it one word i.e., .when('/firstPart/secondPart1SecondPart2/thrirdPart', {
templateUrl: '/path/to/file'
})
everything works as expected even when the user hits the refresh button. It is first going through the angular router and interceptor attaches the Authorization header and then goes to make a get request for that template.
Wondering, is there any problem in using hyphen in URLs? However, I do not wish to remove the hyphens as I have already used it in many places and also I feel its good to have - between two words that needs to be displayed together in the URL than making them camel cased.
S, finally I have two questions :
1. How to load the same page as the user was in before he hit refresh, instead of redirecting him to '/' or login url.
2. The problem explained above, occurs only for hyphenated(-) URLs, what is the problem having '-' in the URL.

Angular UI Router Otherwise fails to redirect

I'm trying to setup and 404 page on my website by using
$urlRouterProvider.otherwise("/404");
but this only works for URLs that do not have multiple slashes/parameters. The following is all of my URLs and states in the same order as in my code:
Home – /
404 – /404
About – /about-us
Privacy – /privacy-policy
Terms – /terms-conditions
Subscribe – /subscribe
Author – /author/:author
Topic – /:category/page/:pageNumber
Post – /:category/:title
If there is a url with two slashes (Ex: /qwkhdjqkwnd/q1weuih), my app thinks it's a Post and tries to fetch information but this obviously fails – it does not know that this is not a valid URL, and thus does not redirect to my 404 page.
What's the best practice for this? Should I allow the app to try and fetch data using the invalid URL and, redirect the state when it fails?
Checking for an undefined object and redirecting to /404 worked for my purposes.

Single page application using AngularJS

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 to provide a specific link to angularJs routed page

I have an angularJs application, which uses $routeProvider to handle internal routing. The back end uses Rest controllers within a Spring Boot application. The application is based on this: https://spring.io/guides/tutorials/spring-security-and-angular-js/
What I want to do is send an email with an embedded link similar to "http://localhost:8080/link/key1234". The user should be able to click this, and go to specific content as indicated by the key1234 variable.
I have seen a similar item (Refreshing page gives "Page not found") which suggests using .htaccess to handle this, but I do not currently have a .htaccess file.
I also have html5mode on [$locationProvider.html5Mode(true);]
Another suggestion (Spring Boot with AngularJS html5Mode) is to intercept the request and redirect to the home page. Whilst this prevents the application from failing, I need the user to go to a specific page, not the Home page.
I have managed to get quite confused about the interactions of my different components. Can you point me in the right direction to enable a specific link to be provided ?
UPDATE
I think that the .htaccess file is a red herring.
The spring.io tutorial includes the following code:
#RequestMapping(value = "/{[path:[^\\.]*}")
public String redirect() {
return "forward:/";
}
And this segment performs a redirect for some of the pages.
However, my tests (until recently) had been using "http://localhost:8080/public/about" which is not getting picked up by the RequestMapping snippet above.
If I use a single level url (e.g. "http://localhost:8080/test") then my existing code works fine.
It looks like there is a flaw in this regex.
When a request like http://localhost:8080/link/key1234 hits your server, you would need to forward the request to home page. Then, the client should get the response of the home page, while the URL will still be http://localhost:8080/link/key1234. html5mode will then come to play, changing the view at the client side.
I think the best way to do it might be to use urlrewrite filter, which should forward all requests except those starting with, say /api/**, to the home page.

angularjs technique for login then redirecting to dashboard page

I'am doing my first AngularJS project with ASP.NET Web API backend. What I am trying to do is, whenever a user visits www.mydomain.com, a login page (index.html) will displayed. After successfull login, he will be redirected to the dashboard.html (this is the shell page, partial views go here). My project structure is shown below-
I am confused about some issues:
Is this the best/common practices what i am trying to do in above?
As because dashboard.html is the main page, should i place app.js on dashboard.html?
If i put app.js on dashboard.html, will index.html (login page) have another app.js (i.e. loginApp.js)?
How should I manage the login state i.e. IsUserLoggedId, UserId etc in angular part?
This question may be silly. I googled, but did not find any example/article addressing such issue.
Would you please help?
Thank you in advance.
I am not sure how ASP.NET deals with it, but to my knowledge ASP.NET is just a server side framework whereas AngularJS is client side framework.
These two framework solve different problem, but has some overlapping features.
If you start using angularjs, then most of the time you will deal with the term "Single Page Application (SPA)".
There are different approaches in how you can handle the url redirection after login. I will just show you two example. There are many more how you can handle the user authentication and session.
First Approach:
In SPA, most of the time browser will change the url route and state directly in the page itself without making the entire page request from the server.
With that said, your dashboard.html will most likely be come a static template file which will be loaded from the browser directly. (i.e. the server does not dynamically parse the dashboard.html but only serve as a static file). Upon the user login, the angularjs will fire a asynchronous HTTP request into the ASP.NET authentication end point. A successful login may return a token to the browser, and the client will use it to manage the user session. At the same time, the Angular will have to change the route to /dashboard/. Notice that that the entire flow happens transparent to the user, it does not fire a full page HTTP request.
Second Approach:
Alternatively, if you choose to redirect from the server, you will have to send a HTTP Redirect 302. and since HTTP redirect will eventually call make a full HTTP request to /dashboard/, and it will then have to reload and bootstrap the angular app.js from the browser again. In this case, the user will have to wait for the dashboard page to be processed by the server upon login
Issues:
Is this the best/common practices what i am trying to do in above? there are many approaches, I think it is best to find the one that works for you. If you have a RESTful API, then you might want to have a look at the SPA approach in more detail.
As because dashboard.html is the main page, should i place app.js on dashboard.html? in SPA, you don't need to load app.js twice. but if you use the second approach, you have to reload the app.js again.
If i put app.js on dashboard.html, will index.html (login page) have another app.js (i.e. loginApp.js)? depends on your approach as stated above
How should I manage the login state i.e. IsUserLoggedId, UserId etc in angular part? Authentication Strategy, UNIX style authorization
There are more official guide that can help AngularJS Developer Guide.
Hope this helps you to integrate with the ASP.NET authentication mechanism.
you should have multiple shell pages. this link can help you...
refer to Multiple Shell Pages part.

Resources