Enabling HTML 5 Mode in AngularJS 1.2 - javascript

I'm working on an app that needs to use HTML 5 mode. Due to the fact that I am migrating an existing site to use AngularJS 1.2, I cannot have '#' tags in my URL. Currently, I have the following:
angular.module('myApp', ['ngRoute']).
config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$routeProvider
.when("/home", {templateUrl:'home.html', controller:'homeController'})
// other routes are defined here..
.otherwise({redirectTo: '/home'});
}]);
Unfortunately, when I visit 'http://myServer/home', my app does not work when html 5 mode is enabled. I get a 404. However, when I visit http://myServer/ it works. Its like deep-linking doesn't work when I have html5 mode enabled. If I comment out the line that says "$locationProvider.html5mode(true);", the site functions. However, once again, I cannot have hash tags in my URL due to the fact I'm migrating an existing site.
Am I misunderstanding how html5mode(true) works? Or, am I doing something wrong?
Thank you

If you're using html5mode you need make changes on the server side to return your entry point index.html (main app page) on any URL request. Then angular app will parse URL and load needed page.

Here's a list of solutions for most common web servers: Apache, nginx, IIS and express.
https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#wiki-how-to-configure-your-server-to-work-with-html5mode
The link is in ui-router's wiki, but it has nothing to do with it, this answer is valid with ngRoute.

I had a similar problem while setting up my app. I was trying to implement pretty URLs as the # in the URL was very disturbing. This is how I solved the problem.
Step 1: Inject the location provider in your app module and set html5mode to true
$locationProvider.html5Mode(true);
Step 2: Insert the base tag in your index.html
Some people say this is not required but I got an error when I tried removing the tag and implementing the same. It says locationProvider requires a base tag.
<base href="/specify-app-directory-here/">
If it is in the root, the following line will suffice
<base href="/">
Step 3: You will need to setup URL rewritting on your server. I, myself am a beginner but found it quite simple. If you are using an Apache just this is how you do it.
Create an .htaccess and place it in the same directory as your index.html, or you can even use an existing one. Add the following lines to the .htaccess
Options +FollowSymLinks
RewriteEngine On
RewriteBase /base-as-specified-in-base-tag/
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([a-zA-Z]+)$ #/$1 [NC,L]
The last line is what is very important. Basically it tells your server if it finds any links of the form "/home" it will redirect it to "/#/home" which angularJS can then handle appropriately. In doing so, it does not actually change the url displayed in the address bar and you have a pretty url. If you try reloading the page also, you will not get a 404 error.
Hope this helps.

first enable $locationProvider.html5Mode(true);
after enabling html 5 mode true you can insert
this code in .htaccess
BEGIN
Options +FollowSymLinks
RewriteEngine on
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^(.*) your file root /index.php [NC,L]
END

Related

How can I prevent angular from removing query parameters on production mode?

I'm building a web app for my job that uses angular 10 as frontend and Spring boot 2.2 for backend.
It's a very simple app with just one route, but this is route can receive a query parameter and show a different HTMLitem depending on the parameter
These are my routes:
const routes: Routes = [
{path:'mainapp', component: HomeComponent},
{path: '', redirectTo: '/mainapp', pathMatch:'full'}
]
The app works great in development mode, I mean when I run my war file with java and then run ng serve, all is good
However, when I generate the production build, in the /resources/static folder so Spring boot can serve my angular app as a static site, there are some issues.
The first issue is when I try to navigate to localhost:8080:/?report=weekly, it redirects me to localhost:8080:/mainapp and removes my query parameter.
The second issue is when I try to navigate to either localhost:8080:/mainapp or localhost:8080:/mainapp?report=weekly it shows a Whitelabel error page with a 404 error code. Even when I refresh the site
I encountered a similar issue before when I tried to deploy an Angular app to a VPS, and at that time it worked for me to add a .htaccess file with a few commands, so I tried this as well here, this is the file I added:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^(.*) /index.html [NC,L]
But apparently, this did not work. This file was added at the same level where my angular.json file is.
This is my project folder structure
I have the angular app in the Ui folder
I am not sure what else could I should you, but if you need any other information about my project let me know.
Also since this is a work-related project I can't upload the code directly, however, I'm trying to replicate the basic architecture to upload it to Github
Until then, can somebody point me in the right direction? How can I fix this route?
Thanks!
So after a couple of try and error seasons, I managed to make this work by adding a controller that redirects to my index
#Controller
public class ViewController {
#RequestMapping("/mainapp")
public String index(){
return "forward:/index.html";
}
}
Just in case someone else is having the same issue

How to deploy Nuxt.js in SPA mode on server properly?

I use Nuxt.js in SPA mode in my project. But I can't properly deploy it in my server (Apache). Has anyone had that experience?
I think that the problem is in trailing slash in URL tried to set DirectorySlash Off in my .htaccess, but then it just doesn't work.
Also tried
Does not help as well:
DirectorySlash Off
#removing trailing slash
RewriteCond %{THE_REQUEST_FILENAME} /(.*)/( |$|?)
RewriteRule ^(.*)/$ $1 [R=301,L]
# internally add the slash back
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_URI} !/$
RewriteRule ^(.*)$ /$1/ [L]
My project is on http://4dea.ru/works/TEST/spc/ now. If you push the button (in the section with the picture of the man on the boat on background) you will go to http://4dea.ru/works/TEST/spc/morskie-konstrukcii and everything works fine. But if you refresh the page, some pictures are missing (in the header, for example).
On the local server (Node.js) everything works fine.
Figured out two ways to do that:
1. Instead of href="image.png" use href="/image.png", so the path to the image will be absolute and accessible from every page. But this option doesn't work if the app is not located in the root directory (like in my case).
2. Load images from assets folder via href="#/assets/image.png". For styles and dynamic paths :style="{backgroundImage: ``url('${require('#/assets/boat.jpg')}')``}" can be used.
Hope it helps you ^^

AngularJs Routes and Refreshing

Routes is what I am using in AngularJs to load dynamic content through an ajax calls asynchronously. This is how I do that:
var $app = angular.module('app', ['ngRoute']);
$app.config(["$routeProvider", "$locationProvider", function ($routeProvider, $locationProvider) {
$routeProvider
.when("/pop", {controller: "popCtrl", templateUrl: "partials/pop_test.html"})
.when("/dashboard", {controller: "dashBoardCtrl", templateUrl: "partials/dashboard.html"})
.otherwise({redirectTo: "/"})
$locationProvider.html5Mode(true);
}])
I also have a mini nav set up so that when I click on my links it loads those partials through the templatrUrl parameter
<ul>
<li>Home</li>
<li>Pop</li>
<li>Dashboard</li>
</ul>
This is all working great, when I click on my links it loaded the content I have set up in pop_test.html and dashboard.html
Now the problem that I am having.
When you click on the link for lets say dashboard the content loads just fine through ng-view and the routes work great BUT if the user reloads or refreshes the page and you're on lets say localhost/dashboard it will actually try to go to that link and locate a file named after whatever you have after / which in this case is a directory called dashboard.
So how can I make it so when the user refreshes or reloads the page he doesn't actually reload the /dashboard page therefor not getting a server error page not found.
As Alberto mentioned, the server needs to know what to do. In Angular's case, everything needs to be routed through the index.html when using $locationProvider.html5Mode(true); otherwise you'll run into what you are now.
To fix this you need to add a Server Rewrite rule which you can find an explanation of it, along with the different server versions, in ui-router's docs here.
You can also add a .htaccess file with the rewrite rules for index.html like so:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^(.*) /index.html [NC,L]

How to have single page application without # inside the URL using Angularjs?

I am trying to build an single page application with angular js.
But i don't want # inside the url when the template is included.
I have used the
$locationProvider.html5Mode(true)
app.config(['$routeProvider', '$locationProvider',
function ($routeProvider, $locationProvider) {
$routeProvider.
when('/dashboardnew', {
templateUrl: './dashboard_tmp',
controller: 'CategoryCtrl'
}).
otherwise({
redirectTo: '/dashboardnew'
});
// use the HTML5 History API
$locationProvider.html5Mode(true);
}]);
but this didn't work when the page is reloaded.
How should I solve this problem?
Thanks
You cannot, that's the compromise. The html5 mode only works if angular is loaded, which is why it will not work if the page is reloaded or if paths are bookmarked.
Stick with the #, people are starting to get used to seeing them
ofcourse you can, use html5 mode in angular and rewrite every (non-api) request to your angular home page on server side. angular will pick up url and go to url location
You need to edit your .htaccess file
RewriteEngine on
# Don't rewrite files or directories
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
# Rewrite everything else to index.html to allow html5 state links
RewriteRule ^ index.php [L]
RewriteRule: index.php or index.html

Forcing a specific page to use HTTPS with angularjs

In our application we have a payment page that we want to use SSL on because we are handling credit card information. We've already put in place rewrite rules for apache to redirect a request to the specific page to HTTPS -- which takes care of any direct requests to the payment page ( http://oursite.com/pay ).
However most navigation in our site is done via relative urls and states using ui-router in angularjs and we have found that apache does not catch these requests and so serves the page without SSL.
EX If a user clicks a link with ui-sref='pay' ui-router loads the template and refreshes the state -- at no point is a request made to the server for a new uri so apache can't redirect to https
Is there a way to force ui-router(or angular in general) to force a state to use HTTPS without having to change all links to reload the entire site?
Of course this may also be a shortcoming in our rewrite rules...Here's what we have so far
RewriteEngine on
RewriteCond %{HTTPS} !=on
RewriteCond %{REQUEST_URI} /pay
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^ index.html [L]
The second set of rules is to enforce html5mode for our app.
RewriteCond %{REQUEST_FILENAME} !-f is in place so that angular can fetch the payment template for the state without needing SSL. Is this okay?
I had a similar problem, although was using $routeProvider in a SPA application. What I did was to enforce a redirect inside the controller:
var forceSSL = function () {
if ($location.protocol() !== 'https') {
$window.location.href = $location.absUrl().replace('http', 'https');
}
};
forceSSL();
This though does reload all resources. However, this happens only once when switching to SSL mode.
Note, the function is actually in a service so can be called from anywhere.
I hope this helps.

Categories