Mix Austria Mix Austria - 9 days ago 3
Node.js Question

Router.use() requires middleware functions

I use express to serve angular html file. I want to test if angular can get data from express backend.

app.component.html

<h1>
{{title}}
</h1>
<a class="button" href="/Books/getall">Get all books</a>


server.js

const express = require('express');

var app = express();
var staticRoot = __dirname;

app.set('port', (process.env.PORT || 3000));

var bookRouter = require('./bookController');

app.use(express.static(staticRoot));

app.get('/', function(req, res) {
res.sendFile('index.html');
});

app.use('/Books', bookRouter);

app.listen(app.get('port'), function() {
console.log('app running on port', app.get('port'));
});


bookController.js

var express = require('express');
var mongoose = require('mongoose');
var Books = require('./books.model');
var bookRouter = express.Router();

var router = function(){
bookRouter.use('/getall')
.get(function(req, res){
var url = 'mongodb://admin:password@ds019076.mlab.com:19076/booksdbtest';
mongoose.connect(url, function(err){
Books.find()
.exec(function(err, results){
res.send(results);
mongoose.disconnect();
});
});
});
};

module.exports = router;


But I got some error like I mentioned on the title. I have read some articles and discussions that says i need some proxy when using express and angular 2 together but I really don't know how to implement that. Can someone help me here on what is wrong with the code? That would be so much appreciated.

EDIT:
I have found what caused the error. I have changed bookRouter.use -> bookRouter.route and the error is gone. Now another problem appears. If I click the link it will load continously and nothing happens. Anyone know why?

Answer

If you are using Angular2 with Express you need to hand off the front end routes to Angular2 and then use Express for the back end points.

In most cases you will receive problems not using some sort of template engine. I like to use Express-Handlebars.

 npm install hbs

Once you have this installed you can set it up in your app.js file. The file you set Express up in.

// view engine setup
app.set('views', path.join(__dirname, 'public'));
app.set('view engine', 'hbs');

Also make sure you have a public directory. If not create one.

/public

Then in the app.js

app.use(express.static(path.join(__dirname, '/public')));

Now you can put css, js, or images in this directory and call them inside your app.

Also inside the public directory you can put your index.hbs file.

Express-Handlebars uses hbs files. In our case you are only going to need one.

This is the file you would need to put the head of your html file in. As well as the

<my-app>Loading...</my-app>

We will pass this off to Angular2.

Now that we have that setup lets make a route to pass it off.

/routes/index.js

var express = require('express');
var router = express.Router();

// pass front end off to Angular2 
router.get('/', function(req, res, next) {
    res.render('index');
});

module.exports = router;

So now when the app loads it will load that index page. So that is the only route we need for now to pass the front end off. At this point we will configure angular2.

Webpack

What is Webpack?

Webpack is a powerful module bundler. A bundle is a JavaScript file that incorporate assets that belong together and should be served to the client in a response to a single file request. A bundle can include JavaScript, CSS styles, HTML, and almost any other kind of file.

I do not know how you have included Angular2 into your project. But if you have not set it up yet and do not know how I suggest using Webpack Follow this tutorial to get it setup. Sometimes it is easier to start over.

Angular2

If you go into your Angular2 application now which for me is at

/assets/app/

You will set up your components and their own routing. Any links created for the front views will be done here now. So in the /assets/app directory you will need a app.routing.ts file.

Routing in Angular2

There are many ways to build this file. I like to use templates then child templates which would be to much to explain in this answer. For you though a basic routing file will look like this.

import { Routes, RouterModule }     from "@angular/router";

import { AboutComponent }           from './about.component';
import { HomeComponent }            from './home.component';


const APP_ROUTES: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', component: HomeComponent },
{ path: 'about', component: AboutComponent },
];



export const routing = RouterModule.forRoot(APP_ROUTES);

Links

Now that you have routes setup in Angular2 you can create links in your html files or home.component.html like this,

 <li class="nav-item p-x-1">
                <a class="nav-link" routerLinkActive="active" [routerLink]="['/home']"> Home</a>
            </li>

I realize this has not basically given you code that will compile which in a perfect world we would all share like that. But I really understand the struggle and want to help. There is just to much to explain to be able to hand you over that much and it make sense. Please use the tutorial I gave you above. If you have any questions ask. Try and use my answer as a baseline to understand the different components of putting together an application like this.

Disclaimer

You do not have to use Express-Handlebars. If you find in that tutorial they are doing something different just follow along so you can get a working app you understand. I like hbs because I only use it for one file then handle everything on the front end with Angular2. The reason I use it instead of just an html file is because it is a huge pain to configure Express to work right with Angular2. For example if you just use an html file then add it to the public directory then run your app and refresh the page you will get a 404 error. Unless you add something like,

HashLocationStrategy

Which adds ugly hash tags to your url and is annoying in a whole different way. Using a template engine for that small task makes everything work so much easier and better. The configuration is minimal as you can see above.

For a seed project I use,

git clone https://github.com/wuno/md-recruit.git

in the terminal navigate to the new directory you just cloned.

type,

webpack

Then

npm start

Then navigate to localhost:3000

Make sure you have webpack installed globally

npm install webpack -g 

It is very important that what ever version of webpack is installed locally in your project has to match the global install.