I'm using Angular Routes to determine the view to be displayed to the user as follows:
define(['angular', './app'], function(angular, app) {
'use strict';
return angular.module('app', ['ngRoute']).
config(function($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl:'assets/partials/partial1.html',
controller: 'MyCtrl1'
}).when('/mada', {
templateUrl:'assets/partials/partial2.html',
controller: 'MyCtrl2'
})
.otherwise({redirectTo: '/'});
});
});
At the moment, the routing works but only like this: localhost/#/mada or localhost/#/
I would like to be able to see localhost/mada
I am aware that adding
$locationProvider.html5Mode(true);
would get rid of the hash. But this still doesn't enable a user to go to: localhost/mada as this returns a server 404.
Can this be achieved? How?
if you are not using server side language then put this code in html head.
<base href="/">
like :
<head>
<base href="/">
</head>
and put this in config block:
$locationProvider.html5Mode(true);
if you are using server side language then use this code:
app.get('*', function(req, res) {
res.render('index');
});
instead of
app.get('/', function(req, res) {
res.render('index');
});
and and put this code in config block:
$locationProvider.html5Mode(true);
Related
I have written 2 ng-app in one project, one is user and the other admin.
To remove the # from the url I had used the below code in both app.config function
$locationProvider.html5Mode(true);
and in app/index.html
<base href="/">
and in app/admin/index.html
<base href="/admin/">
user app.js
app.config(['$routeProvider','$locationProvider',
function($routeProvider, $locationProvider) {
$routeProvider.
when('/properties', {
templateUrl: 'views/modules/properties.html'
})
.when('/pages', {
templateUrl: 'views/pages/pages.html'
})
.when('pages/editpages', {
templateUrl: 'views/pages/editPages.html',
controller: 'editPagesController',
});
$locationProvider.html5Mode(true);
}
]);
server.js
app.use('/', express.static('app', { redirect: false }));
app.get('/*', function(req, res){
res.sendFile(__dirname + '/app/index.html');
});
I'm getting the following error, if there's an extra param in the route
Uncaught SyntaxError: Unexpected token <
The above error I get when my urls are
http://localhost:8080/properties/
http://localhost:8080/properties/something
http://localhost:8080/pages/
http://localhost:8080/pages/editpages
This works fine if the url is used without the last / i.e.
http://localhost:8080/properties
http://localhost:8080/pages
I have refered to this questions too but couldn't resolve the issue
Node / Angular app Uncaught SyntaxError: Unexpected token <
How to use multiple index pages in angular
Solution found
The placement of the <base href="/"> was just before the </head> before which there were all scripts and links tags. After adding the <base href="/"> after title tag the issue was resolved
The problem is with the express middleware, take for example
app.use(express.static('./build/'));
// Any invalid calls for templateUrls are under app/* and should return 404
app.use('/app/*', function(req, res, next) {
four0four.send404(req, res);
});
// Any deep link calls should return index.html
app.use('/*', express.static('./build/index.html'));
I have creating a nodejs backend with an angular js front end. I have the following angularjs code for routing.
var myApp = angular.module('myApp ', ['ngRoute']);
myApp .config(['$routeProvider', '$locationProvider', function($routeProvider){
$routeProvider
.when('/login', {
templateUrl : 'login.html',
controller: 'loginController'
}).otherwise({
templateUrl : 'main.html',
controller : 'mainController'
});
}]);
and my app.js contains the following code. (note: I am using the express js framework 3.0)
app.use(app.router);
app.use('/',function(req, res) {
res.sendfile(__dirname + '/public/index.html');
});
I put all the htmls in the public folder and the structure is something like this.
public/
-css folder
-angular dependencies
-all my htmls (index.html,login.html,main.html)
routes/
-index.js
views/
-index.ejs
-error.ejs
app.js
Now when I hit my base url the index.html loads based on the code I gave in the app.js given above. then the angular inserts the main.html code in the ng-view div. When I hit the /login I want the login.html to be loaded. But instead the same main.html is being loaded. can someone throw light on this? There are few solutions but none came to my rescue.
How to use AngularJS routes with Express (Node.js) when a new page is requested?
This helped me.
I made changes as
myApp.config(['$routeProvider', '$locationProvider',
function($routeProvider,$locationProvider){
$routeProvider
.when('/login', {
templateUrl : 'login.html',
controller: 'loginController'
}).when('/', {
templateUrl : 'main.html',
controller : 'mainController'
});
$locationProvider.html5Mode(true);
}]);
changes to app.js
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(__dirname + '/public'));
app.use(app.router);
app.use('/',function(req, res) {
res.sendfile(__dirname + '/public/index.html');
});
I think you want something along the lines of express.static
app.use(express.static(__dirname + '/public'));
If a request comes in for "login.html" it'll check the public directory for that file first.
I am trying to reload the page mannually from the browser but it doesn't work and says
Cannot GET /rate/4
My route:
angular.module('routing')
.config(function ($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl: 'app/views/index.html'
})
.when('/rate/:cid', {
templateUrl: 'app/views/rate.html'
})
.otherwise({
'redirectTo': '/'
});
$locationProvider.html5Mode(true);
});
My assumption is that when I am reloading the main (index.html) is not loaded which is my base html file.
You do not have an angular problem, you have a server problem.
You're essentially working with a single page application.
When the server receives a request for rate/4 it must return index.html (or whatever the name that your main page is).
How you solve this will depend upon what platform you've implemented your server in.
For example, if you were running a node express server, you would have this kind of routing code:
app.get(/^\/rate\/.*/, function(req, res) {
// This matches a known pattern for a client-side route
res.sendFile(__dirname + '\\public\index.html');
});
I have started an application where I use Express 4.0 server. I have set up the routes based heavily on a tutorial on scotch.io (http://scotch.io/tutorials/javascript/build-a-restful-api-using-node-and-express-4), builiding a backend api to serve the front end SPA (angularjs). Here is an extract of the backend router:
router.route('/users')
.get(function (req, res) {
User.find(function(err, users) {
if (err) {
res.send(err);
}
else {
res.json(users);
}
});
})
Further down
// home page route (http://localhost:8080)
router.get('/', function(req, res) {
res.send('API ROOT');
});
app.use('/api', router);
From the frontend i use just a get to get the users from the api:
$http.get('/api/users')
.success(function(data) {
$scope.users = data;
});
and the angular routes are set up like this:
.when('/', {
templateUrl: 'views/home.html',
controller: 'MainController'
})
.when('/users', {
templateUrl: 'views/user.html',
controller: 'UserController'
})
The index.html has a link to /users.
When starting the server and goint into localhost:8080 it loads fine, and clicking the users loads the user.html view and lists the users.
However, if i click refresh when browser is in localhost:8080/users
I get:
Cannot get /users
Is it a controller issue?
Or is it a problem with backend routing?
Any feedback/suggestions would be very welcome!
Searching some more, I see that there are several sollutions that might fix this:
Either on the frontend (angular routes part) adding this to the end:
// >>> redirect other routes to
otherwise({
redirectTo: '/'
});
Or on the backend (after all your routes):
app.get('*', function(req, res){
res.render('index.html');
});
Which sollution is better (or is it reccomended to use both...?)
You should use both.
You need to provide a catch-all / wildcard route to your express application such that any routes that are not explicitly matched will return the index page which will load Angular and allow your Angular routes to then take over. Note that this should always be your last route (they are parsed in order).
app.get('*', function(req, res){
res.render('index.html');
});
Then in your Angular app you should have a default route to catch any un-matched routes on the client side. This route will come into effect if the application is already loaded but an unknown route is encountered whereas the server side solution above will handle any direct requests.
function($routeProvider) {
$routeProvider.
when('/', {
templateUrl: 'home.html',
controller: 'homeCtrl'
}).
otherwise({
redirectTo: '/'
});
}]);
I have an angular app with a directory structure
app
..views
....partials
......main.jade
......foo.jade
....index.jade
and routes defined like:
'use strict';
angular.module('myApp', [
'ngCookies',
'ngResource',
'ngSanitize',
'ngRoute',
'firebase',
'myApp.config'
])
.config(function ($routeProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$routeProvider
.when('/', {
templateUrl: '/partials/main',
controller: 'MainCtrl'
})
.when('/foo/:fooName', {
templateUrl: '/partials/foo',
controller: 'FooCtrl'
})
.otherwise({
redirectTo: '/'
});
});
I'm using express on the server side and the relevant code is:
// server.js
app.configure('development', function(){
app.use(express.static(path.join(__dirname, '.tmp')));
app.use(express.static(path.join(__dirname, 'app')));
app.use(express.errorHandler());
});
app.configure('production', function(){
app.use(express.favicon(path.join(__dirname, 'public/favicon.ico')));
app.use(express.static(path.join(__dirname, 'public')));
});
app.get('/', routes.index);
app.get('/partials/:name', routes.partials);
//routes.js
exports.index = function(req, res){
res.render('index');
};
exports.partials = function(req, res){
var name = req.params.name;
res.render('partials/' + name);
};
The main route "/" loads fine and when i click to "/foo/bar" the partial view foo.jade loads as expected. However, when I try visiting "/foo/bar" directly in the URL i get a 404 response from Express "cannot GET /foo/bar" which makes sense since there's no route like this defined in express. However, I thought this was the whole point of defining the angular router..i.e. it's supposed to intercept this request and actually ask for "/partials/foo".
I tried adding
//redirect all others to the index (HTML5 history)
app.get('*', routes.index);
but it didnt solve the issue and seemed to be catching even the requests for static js assets and responding with the contents of index.html which is pretty bad.
I'm sure I'm doing something wrong. How can I fix things so that I can directly visit the URLs?
The reason routing is behaving like this is html5mode turned on.
Notice the line: $locationProvider.html5Mode(true);
You need to understand that when you try to access "/foo/bar" directly your browser sends HTTP GET request to this URL. When you try to access this url via link clicking, like you said, Angular is intercepting this action and calls History.pushState that only updates browser's link.
What you need to do in order to make html5mode routing work is implementing url rewrite. Every request has to be redirected to your index file that bootstraps AngularJS application, but this needs to be done on your server. Angular will render the desired page by itself.
Check out connect mod rewrite grunt task that does exacly that.
You can also you this middleware directly.