remove hashes when dealing with routes in AngularJS - angularjs

I have made a sample SPA using angular. I used Angular routing feature, to have a single layout page, and then inject and swap out different views depending on the URL the end user has requested.
Everything works perfectly fine with the hashes in the href routes on the index page
page1
but by doing so, my URL of the webpage will be like http://localhost/angular/#/page1
So I wanted to remove the hashes in the URL and make it like http://localhost/angular/page1
To remove the hashes, you will have to enable the html5Mode routing and also set the base href on the index page
https://docs.angularjs.org/error/$location/nobase
I did exactly the same (please see my code snippet below), however it does not work. I'm running this on local host Apache server.
var app = angular.module("myModule", ["ngRoute"])
.config(function($routeProvider, $locationProvider) {
$routeProvider
.when("/page1", {
templateUrl: "partials/page1.html",
controller: "page1Controller"
})
.when("/page2", {
templateUrl: "partials/page2.html",
controller: "page2Controller"
})
$locationProvider.html5Mode(true);
})
.controller("page1Controller", function($scope) {
$scope.message = "Page1";
})
.controller("page2Controller", function($scope) {
$scope.message = "Page2";
})
<html ng-app="myModule">
<head>
<title>Angular Routing</title>
<script type="text/javascript" src="angular.js"></script>
<script type="text/javascript" src="angular-route.js"></script>
<script type="text/javascript" src="js.js"></script>
<link rel="stylesheet" type="text/css" href="styles.css">
<base href="angular"></base>
</head>
<body>
<table>
<h3>Sammple Routing in AngularJS</h3>
<tr>
<td class="leftMenu">
page1
page2
</td>
<td class="mainContent">
<ng-view></ng-view>
<!--partials will be filled here-->
</td>
</tr>
</table>
</body>

I'm struggling with this on IIS right now and in my struggles, stumbled across an excellent guide for Apache: https://ngmilk.rocks/2015/03/09/angularjs-html5-mode-or-pretty-urls-on-apache-using-htaccess/
I hope it helps.

I followed this article to remove the hashes from URLs: https://scotch.io/tutorials/pretty-urls-in-angularjs-removing-the-hashtag Here is the quick code for what he does:
app.js or every angular page:
app.config(["$locationProvider",
function($locationProvider) {
$locationProvider.html5Mode(true);
}
]);
Angular template or each angular page must include this in the head:
<base href="/">
I'm not at all sure of the inner workings so I can't explain what exactly this does. Everything I know about this is from that article so feel free to take a look.
Edit: Could be a problem with try using an empty string like It prevents hashes from being added to the url when clicking dead links but still gives the anchor hover effect.

Related

Why won't Angular-ui-router's <templateUrl> work when all my files are hosted in S3 bucket?

I'm building a sample AngularJS single-page application that uses Angular-UI-Router. But instead of the usual setup where the Angular application is served up through a web-server, I am running a server-side application that just serves up the index.html page in response to HTTP requests. All other resources needed are just pointers to my AWS S3 bucket or somewhere else.
I am doing this because I want to pre-populate the tags on the server-side with og:title from my database so that the Facebook scraper sees the proper values (as I discussed here). This can't be done purely on the user's client. That's why I have to jump through these hoops.
So when you curl my endpoint, it responds with the following HTML from my index page:
<!DOCTYPE html>
<html>
<head>
<base href="/">
<meta property="og:title" content="Saqib's Pre-filled OG Title!"/>
</head>
<body ng-app="pangolinApp">
<table>
<tr>
<td><a ui-sref="splash"><button>Splash</button></a></td>
<td><a ui-sref="blue"><button>Blue</button></a></td>
<td><a ui-sref="green"><button>Green</button></a></td>
<td><a ui-sref="red"><button>Red</button></a></td>
</tr>
</table>
<ui-view></ui-view>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/1.0.3/angular-ui-router.min.js"></script>
<script src="http://static.predictagram.com/js/app.js" type="text/javascript"></script>
<script src="http://static.predictagram.com/js/splashController.js" type="text/javascript"></script>
<script src="http://static.predictagram.com/js/blueController.js" type="text/javascript"></script>
<script src="http://static.predictagram.com/js/greenController.js" type="text/javascript"></script>
<script src="http://static.predictagram.com/js/redController.js" type="text/javascript"></script>
</body>
</html>
It renders onto the page as expected. Great:
Here are the ui-router states specified in http://static.predictagram.com/js/app.js:
var app = angular.module("pangolinApp", ["ui.router"]);
app.config(function($stateProvider, $urlRouterProvider, $locationProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('splash', {url:'/', templateUrl : "html/splash.html", controller : "SplashCtrl"})
.state('blue', {url:'/blue', template: '<p>Hello From Blue!!</p> <p>Color = {{color}}</p>', controller : "BlueCtrl"})
.state('green', {url:'/green', templateUrl: 'html/green.html', controller : "GreenCtrl"})
.state('red', {url:'/red', templateUrl: 'html/red.html', controller : "RedCtrl"});
$locationProvider.html5Mode(true);
});
However, the problem is that only the Blue button actually works. The other ones don't. I can see that when you press each button it enters the respective controller (because I have put a console.log line in each one). But only the template specified for the blue state is working.
Clearly this is because the blue state uses template and all the other states uses templateUrl. So I suspect it cannot find the files html/red, html/green. html/splash.html. Maybe they are not being served? I don't know. How can I ensure my AngularJS Single-Page-App can access those html templates??
EDIT:
Here is pic of the structure of my angular application. But it is stored in my S3 bucket. So replace angular_app/ with http://static.predictagram.com/:
When you set templateUrl as: templateUrl: 'html/green.html' you are telling angular, that your templates can be found at that local folder (html).
As you are trying to take the templates from a remote server, you have to get them with absolute routes. For example: templateUrl: 'http://yourserver/templates/green.html'
As it is not meant to work like that, you are going to have CORS errors, you can take a look to this question/answer and it may help you:
How get a template from a remote URL with AngularJS

AngularJS ngRoute not working as expected

I'm trying to use the ngRoute in my angularJS page, but I'm not able to load my content within ng-view.
HTML:
<!DOCTYPE html>
<html>
<head>
<title></title>
<link href="CSS/index.css" rel="stylesheet" />
<script src="Scripts/angular.min.js"></script>
<script src="Scripts/angular-route.js"></script>
<script src="Scripts/app/index.js"></script>
</head>
<body ng-app="app">
<header>
<a ng-href="#/add-new">Add new</a>
</header>
<div ng-view></div>
<footer>
#Copyright 2017
</footer>
</body>
</html>
index.js:
var app = angular.module('app', ['ngRoute']);
app.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/add-new', {
template: 'Some content'
})
}]);
Not sure what I'm missing here.
If I add otherwise condition on $routeProvider, it gets loaded. Please let me know what am I missing here so that the content within my $routeProvider.when gets loaded in my ng-view on markup. Thanks
Also not getting any console errors.
try this
JS:
app.config(function($routeProvider) {
$routeProvider
.when("/", {
templateUrl : "index.htm"
})
.when("/add-new", {
templateUrl : "add.htm"
})
});
HTML:
Red
Add this below line in your HTML page
<base href="/">
and change ng-href to href
EDIT :
$location in HTML5 mode requires a <base> tag to be present!
If you using ng-href, the you should pass $scope object
You don't have entry point for the app, so if you load your app and you are not going to specific url you will not see any results.
You can add otherwise({redirectTo:'/add-new'}) or go to #/add-new to see your page

AngularJS routing works on W3Schools but nowhere else

I'm just learning AngularJS and I can't seem to get routing working no matter what I do, even copying examples verbatim.
I'm basing it off the examples provided on W3Schools, such as:
http://www.w3schools.com/angular/tryit.asp?filename=try_ng_routing_template
The page I built is:
<!Doctype html>
<html data-ng-app="SUApp">
<head>
<link rel="stylesheet" type="text/css" href="SUStyleSheet.css" >
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-route.js"></script>
<script src="SUApp.js"></script>
</head>
<body>
<div id="Menu">
<ul>
<li>Create a new box</li>
</ul>
</div>
<div data-ng-view></div>
</body>
</html>
SUApp.js is:
var SUApp = angular.module('SUApp',['ngroute']);
SUApp.config(function($routeProvider){
$routeProvider
.when('/',
{
templateURL:'index.html'
})
.when('/box',
{
templateURL:'box.html'
})
.otherwise({redirectTo: '/'});
});
Box.html:
<div class ="box">
<p>Hello World</p>
</div>
I've gone over it with a fine-toothed comb and I can't find anything technically wrong (which doesn't necessarily mean there isn't). What's really strange, though, is that even if I copy and paste the W3Schools example, it still doesn't work in any browser I've used (Chrome and IE).
Other AngularJS features have worked on the above page and module, for example if I remove the config and add in an controller. It's the config and routing in particular that are conking everything up.
You are missing a '/' in the view,
<ul>
<li>Create a new box</li>
<li>Home</li>
</ul>
Here is the working Plunker
You might need a route without the /.
var SUApp = angular.module('SUApp',['ngroute']);
SUApp.config(function($routeProvider){
$routeProvider
.when('',
{
templateURL:'index.html'
})
.when('/',
{
templateURL:'index.html'
})
.when('/box',
{
templateURL:'box.html'
})
.otherwise({redirectTo: '/'});
});
This is common when using UI router, and I think I had the same problem with the basic Angular router.

Cannot manually navigate to urls

Whenever I manually enter a url into my browser to a site built with Angular, I get:
'HTTP 404
The resource cannot be found
Requested URL: /register'
The only navigable url is http://localhost:XXXX/index.html, from there I have to navigate around the site with anchor tags.
My config file for Angular looks like this:
app.config(function ($locationProvider, $routeProvider) {
$locationProvider.html5Mode(true);
//.hashPrefix('!')
$routeProvider
.when('/', {
templateUrl: '/Client/AngularViews/home.html'
})
.when('/register', {
templateUrl: '/Client/AngularViews/register.html',
controller: 'registerController'
})
.when('/post-register', {
templateUrl: '/Client/AngularViews/postRegister.html',
controller: 'registerController'
})
.otherwise({ templateUrl: 'Client/AngularViews/home.html' });
});
Index.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" data-ng-app="app">
<head>
<script type="text/javascript" src="Scripts/jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="Scripts/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.3/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular-route.js"></script>
<link href="Content/bootstrap.min.css" rel="stylesheet" />
<script type="text/javascript" src="Scripts/mainController.js"></script>
<base href="/" />
</head>
<body>
<div class="container-fluid">
<div ng-view></div>
</div>
Can someone explain to me what I'm doing wrong? I want to be able to manually enter urls into the address bar and navigate to anything other than index.html
According to documentation:
Server side
Using this mode 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 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 handeled by the application.
https://docs.angularjs.org/guide/$location
So you need some additional support from server-side: configure your http server to reply with index.html for all url you have in your apps.
I use ASP.Net MVC for server side URL rewriting using controllers. Probably not its intended use but works well

deep linking, page reloads, angular js

I have a table which should be filtered depending on the url.
This is my module::
angular.module('myApp', ['pipelibservice']).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/pipes/:pipeID', {templateUrl: 'partials/wizard.html', controller: PipeListCtrl});
}]);
In my template I have a list with a href that should filter the table:
<li ng-repeat="pipe in pipes">
<a href='#/pipes/{{ pipe.code }}'>{{ pipe.code }} - {{pipe.title_en}}</a>
</li>
This is my index.html
<!doctype html>
<html ng-app="myApp">
<head>
<meta charset="utf-8">
<title>Google Phone Gallery</title>
<link rel="stylesheet" type="text/css" href="css/bootstrap.css" />
<link rel="stylesheet" type="text/css" href="css/app.css" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.1.4/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-strap/0.7.2/angular-strap.min.js"></script>
<script src="js/app.js"></script>
<script src="js/controllers.js"></script>
<script src="js/services.js"></script>
<script src="lib/angular/angular-resource.js"></script>
</head>
<body>
<div ng-view></div>
</body>
</html>
Problem is, the entire page reloads when I hit the link. I only want the url to change so my table is filtered. How do I fix so the page is not reloaded?
Update:
I've narrowed it down to the rest API call. If i replace the rest call with hardcoded values (from the orginal rest-call) then it works. Any idea what can be wrong?
you cant normally use $route and not refresh the page. but in your case i would just use a filter http://docs.angularjs.org/api/ng.filter:filter
<li ng-repeat="pipe in pipes | filter: pipeID">
<a href='#/pipes/{{ pipe.code }}'>{{ pipe.code }} - {{pipe.title_en}}</a>
</li>
dont forget to put in ctrl $scope.pipeID = $routeParams.pipeID
P.S. i wrote a post explaning a bit simpler Ben Nadels idea (which is awesome) and its a way to use $route without refreshing http://bresleveloper.blogspot.co.il/2013/08/breslevelopers-angularjs-tutorial-basic_20.html
the point is that using $route with templateUrl and/or controller creates new instances of the controller and view, and by ur description u dont want it. so u can drop the templateUrl controller and send a custom parameter and in the app use ngSwitch to switch ngInclude and u manage it all with 1 controller
As per ngHref documentation, you should use ng-click to prevent the page reload:
{{ pipe.code }} - {{pipe.title_en}}
You would need to create the goToPipe function in your controller, with something like:
$scope.goToPipe = function (pipe_code) {
$location.path("/pipe/" + pipe_code);
};
The only solution I've found to this problem so far is this:
http://www.bennadel.com/blog/2441-Nested-Views-Routing-And-Deep-Linking-With-AngularJS.htm
Take a look at their demo:
http://bennadel.github.io/AngularJS-Routing/#/pets/cats/10/medical-history
Notice the tabs BACKGROUND, DIET, MEDICAL HISTORY and how the do not refresh the page.
However this solution is very complex and involves and employing a lot of non-native to angular stuff.
I'm still looking to find a simpler solution to this simple problem.

Resources