7

I will explain the issue in as much detail as possible.

I am attempting to use AngularJS with Express and am running into trouble. I wish to display HTML files (not using a templating engine). These HTML files will have AngularJS directives.
However, I am not able to display a simple HTML file itself!

The directory structure is as follows:

Root  
---->public  
-------->js  
------------>app.js  
------------>controllers.js  
---->views  
-------->index.html  
-------->partials  
------------>test.html  
---->app.js  

The contents of public/js/app.js is:

angular.module('myApp', []).
  config(['$routeProvider', function($routeProvider) {
  $routeProvider.when('/', {templateUrl: 'partials/test.html', controller: IndexCtrl});
$routeProvider.otherwise({redirectTo: '/'});
}]);  

The contents of public/js/controllers/js is:

function IndexCtrl() {  
}  

The contents of the body tag in views/index.html is:

<div ng-view></div>  

That's it. The expectation is that AngularJS will substitute the above view with test.html - views/partials/test.html whose contents are:

This is the test page!  

enclosed within the paragraph tags. That's it!

Finally, the contents of ROOT/app.js file is:

var express = require('express');

var app = module.exports = express();  

// Configuration

app.configure(function(){  
    app.set('views', __dirname + '/views');  
    app.engine('html', require('ejs').renderFile);  
    app.use(express.bodyParser());  
    app.use(express.methodOverride());  
    app.use(express.static(__dirname + '/public'));  
    app.use(app.router);  
});

app.configure('development', function(){  
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));  
});  

app.configure('production', function(){  
  app.use(express.errorHandler());  
});  

// routes

app.get('/', function(request, response) {  
    response.render('index.html');  
});  

// Start server

app.listen(3000, function(){  
  console.log("Express server listening on port %d in %s mode", this.address().port, app.settings.env);  
});  

Now, when I do $node app.js in the root folder, the server starts without any error. However if I go to localhost:3000 in the browser, the URL changes to localhost:3000/#/ and the page gets stuck / freezes. I can't even check the console log in Chrome!
This is the problem that I am facing. Any clue about what I am doing wrong?

callmekatootie
  • 10,989
  • 15
  • 69
  • 104

2 Answers2

8

Finally figured it out - after many intense moments of hair pulling!!
The reason why the page freezes is because (explained step by step):

  1. User launches localhost:3000
  2. This requests the express server for '/'
  3. Express renders index.html
  4. AngularJS will render the template 'partials/test.html'.
  5. Here, I am taking a wild guess - AngularJS has made a HTTP request for the page 'partials/test.html'.
  6. However, you can see that express or rather app.js does not have a handler for this GET request. That is, the following code is missing:

    app.get('partials/:name', function(request, response) {
    var name = request.params.name;
    response.render('partials/' + name);
    });

inside app.js of the ROOT directory. Once I add this code, the page renders as expected.

callmekatootie
  • 10,989
  • 15
  • 69
  • 104
  • Another (better) solution is to put your partials in your `public` folder so they will be served by the static middleware without needing to create specific route for them and without going through router/app stack. Note that your system is going to be very slow for users to load pages as they will need to download the index page from express, load the DOM and Angular, make an Http request call to get the partial, execute Javascript to render the page. Pretty complicated and slow IMO. – WispyCloud Sep 21 '13 at 08:23
  • @jtblin I think your solution is applicable when your templates are public... In my cases, they are restricted and can be accessed only with proper authorizations... – callmekatootie Sep 21 '13 at 19:15
-1

Try following the design pattern in this working fiddle. Code shown below. You can replace the template option with templateUrl and it should still work fine.

var app = angular.module('app', []);

app.config(['$routeProvider', function($routeProvider){
    $routeProvider.when('/', {template: '<p>Index page</p>', controller: 'IndexCtrl'});
    $routeProvider.otherwise({redirect:'/'});
}]);

app.controller('IndexCtrl', function(){

});
grendian
  • 4,148
  • 1
  • 12
  • 7
  • I want to keep the `app.config()` inside app.js and the `app.controller()` inside controllers.js file. However, inside controllers.js, if I use local variable, it does not work. Do not know why – callmekatootie Feb 25 '13 at 10:26