I have a strange issue with UI router and Express interacting together.
I've looked for solutions everywhere but nothing seems to be completely fixing the issue working.
When my app is in my /public folder and when i navigate to / it works fine and the url is getting changed as i click links.But whenever i go directly to /random/path ( ui-sref="post/new"> ), it get intercepted by nodejs and say that this route doesn't exist.
I've fixed that issue using from a topic on that issue :
app.use('/', express.static(__dirname + '/public'));
app.use(function (req, res) {
res.sendFile(__dirname + '/public/');
});
And now everything is working fine whenever i navigate directly to the path i want.
Now there is a new issue where the whole page will reload on every path change instead of just behaving like a client side app should and just load the view + controller.
The strange thing is that it's working as expected for 2 or 3 path.
Can anyone help ?
edit :
angular.module('App').config(function($stateProvider, $locationProvider,$urlRouterProvider) {
$locationProvider.html5Mode(true);
$urlRouterProvider.otherwise('/');
$stateProvider
.state('posts-new', {
url:'/post/new',
templateUrl: 'tmpl1.html'
})
.state('posts', {
url:'/posts',
templateUrl: 'tmpl2.html'
});
});
I've also tried with both base url / and <base href="/index.html">
Alright, so your NodeJS route not existing is because of your route.
It works fine for / because it interprets that as /public/index.html.
If you then try and load /post/new, it looks for /public/post/new/index.html - and doesn't find it.
Fix below should work for you.
app.use(function (req, res) {
res.sendFile(__dirname + '/public/index.html');
});
Then, you'll need a slightly separate way of serving your templates - basically as static files! I'd personally suggest you use a simple folder for templates, as shown below. Make sure this is above your catchall route above.
app.use('/templates', express.static('/public/templates'));
Oh, and finally - you'll want your <base> tag set to /.
Related
I have typically used Angular to create whole websites rather than for parts of a website but now I would like to separate the homepage for SEO purposes so that it's a static HTML file and not part of the AngularJS app.
I'm using ExpressJS on the back-end but I'm not sure how I would serve the index.html and the app/index.html separately. Could someone point me in the right direction?
In server.js I normally have something like this:
app.use(function(req, res) {
res.sendFile(__dirname + '/app/index.html');
});
but what do I need to do to be able to deliver index.html if the user goes to the homepage and app/index.html if the user navigates to /somewhere
I'm trying to avoid the cost of an extra Heroku Application fee if at all possible?
See the code below. You will setup a rule wherein if the url is /home (or whatever your homepage path is), you send the user to index.html and after all the rules (if you have more rules) you will have a catchall rule where you will send user to app/index.html.
app.route('/home')
.get(function(req, res) {
res.sendFile(__dirname + '/index.html');
});
app.route('/*')
.get(function(req, res) {
res.sendFile(__dirname + '/app/index.html');
});
};
I have remove (#) hashbangs by $locationProvider.html5Mode(true) in ui-route.
and set <base href="/public/">
when I have tried to localhost:59940/public/#/home url # is remove and url look localhost:59940/public/home and getting home view.
but when I have tried localhost:59940/public/home url. I have getting 404 Not Found error.
help me for getting home view when try to access localhost:59940/public/home in browser.
The problem is that the browser resolves urls before your angular app responds, and indeed the resource for that route is not there. The solution I have used is to make your 404 route return the index.html page and use ui-router to handle real 404 cases. But another idea is to match all of the client routes to routes on your server which return the index.html.
To enable $locationProvider.html5Mode in angular, you also need to some side server changes.
Other then your static assets and apis path, all other routes should server index.html(your main SPA page) only.
See below code.
This is how you can do it in node.js using express server.
var app = require('express')();
app.configure(function() {
// Static files - all js, css, images, etc go into the static path
app.use('/static', express.static('/static'));
// If a static file is invalid so we send 404
app.use('/static', function(req, res, next) {
res.send(404);
});
// This route deals enables HTML5Mode by forwarding missing files to the index.html
app.all('/*', function(req, res) {
res.sendfile('index.html');
});
});
app.listen(3000);
I am trying to use html5mode in angular, so that I can bookmark a page like http:/myhost/products (where /products is a route defined by$stateProviderRef.state(xxx) ).
To that end I've
added $locationProvider.html5Mode(true) to my app config
added 'base href="/"' (with the <>) to my index.html
added the catch all rewrite to my server.js in node.js
app.get('*', function(req, res) {
res.redirect('/');
});
restarted the node server
so what happens is that the app starts ok, all navigation works, I can go to http://myhost/products and everything works well.
However, if I press refresh at this point, I am redirected back to the index page. Looks to me as if ui-router is either losing the path (/products) or I have missed something in the config / setup
I have been browsing through the questions on StackOverflow until my eyes are bleeding, but all of the solutions to similar problems are things that I've already done (base=, redirect etc)
Anyone else has this problem and solved it ? Would be much appreciated if you could share your findings.
Thanks
You shouldn't redirect in server like that
app.get('*', function(req, res) { res.redirect('/'); });
Instead, send same index.html
app.route('/*')
.get(function(req, res) {
res.sendFile(path.resolve(app.get('appPath') + '/index.html'));
});
Take a look at this generator for more
https://github.com/DaftMonk/generator-angular-fullstack/blob/master/app/templates/server/routes.js
I'm trying to remove # from my angularjs urls using
$locationProvider.html5Mode(true);
$locationProvider.hashPrefix('!');
and <base href="/"> in my index.html and i have changed the hrefs in my partials from #/abc to /abc
it works fine when navigating through links within the site, however except my home page, on every other page, when i try to reload the page or copy and paste the link(and hit enter) it gives me error. i have done alot of search online with no luck. i'm hoping someone here has already gone through this and can help me.
thanks
So if you are using jade you shall do the following:
app.get('/', index);
// while index is defined in routes.js and jade is defined as template engine
If you're using angularjs templating engine with normal html files, do the following:
exports.index = function(req, res) {
res.sendfile(__dirname + "/public/index.html");
};
app.get('/', index);
I'm using AngularJS and ExpressJS and having an issue with routing. I saw many other posts but none of those solutions seemed to work. Here is my routes in Express:
module.exports = function(app, auth) {
//Api routes
var mycontroller = require('../app/controllers/mycontroller');
app.get('/api/dostuff/:id', mycontroller.getBlockByHash);
//Home route
app.get("/", function(req, res) {
res.render('index');
});
};
When I go to my root /, everything works as expected. ExpressJS serves up my index and angular picks up the rest. When I click a link /blocks, it works as expected since AngularJS picks up the route. But when I refresh, I get a 404 not found error.
I tried app.get('*' instead, but that gives me a completely different error where nothing loads.
I'm using Jade to create the basic page structure with Express. My Express config is:
app.use(express.favicon());
app.use(express.static(config.root + '/public'));
When using html5Mode the documentation says:
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)
What it doesn't mention is:
You should exclude static assets like scripts/styles/images/fonts etc.
You should also exclude your Restful API.
Your case:
The error you got there is express serving html into script tags and the browser fails to parse them as a valid javascript.
Use express.static to serve static assets and then use app.get('*', for redirecting all other requests to your angular.js entry point (index.html).
express.js middleware order do counts!
express.static must be declared before app.router
Node.js / Express.js - How does app.router work?