Create your account

Already have an account? Login here

Create account

Setting up an Angular 4 MEAN Stack (Tutorial)

By Gary simon - Aug 10, 2017

To develop more robust Angular apps, sometimes it's necessary to integrate Angular (the frontend) with an actual backend.

One such popular stack for achieving this is the MEAN stack. It's an acronym for:

  • MongoDB
  • Express.js
  • Angular
  • Nodejs

All 4 of these technologies allow you to create powerful apps.

The Angular team pushes out a lot of updates. Within 2017, Angular will have gone from version 2, to 4, and ultimately to 5 in September. Because of this, it has been difficult for developers to find reliable MEAN configurations that will work with the latest version of Angular.

Fortunately, here's a brand spanking new tutorial that will provide you with a working MEAN4 (and soon, MEAN5) stack. So, let's get started!

Note: If this tutorial is outdated and something doesn't work, let us know in the comments!

If you prefer watching a video..

Be sure to Subscribe to the Official Coursetro Youtube Channel for more awesome videos!

(Step 1) Installing Nodejs

Before we begin, it's important to note that with exception to this step (installing Nodejs), there isn't a required step-by-step process for installing Express, Angular and MongoDB. Any steps after this initial step can come in any order.

To have access to the Node Package Manager (NPM) and run our Express server, we need to first install Nodejs.

You may already have it installed. To check whether it's installed, visit your console and type:

$ node -v

If it goes unrecognized, you will need to visit Nodejs.org and visit the downloads page. Choose the installer appropriate for your OS, and install it.

Once complete, reload your console/command line, and re-run the node -v command. This time it should provide you with the version installed.

(Step 2) Installing Angular

We're going to use the Angular CLI to create our Angular app. Let's install it at the command line through NPM.

$ npm install @angular/cli -g

Once installed, hop into the folder where you prefer to store your projects and run the following command:

$ ng new mean
$ cd mean

Once you're in the new project folder, we're going to run a command with the Angular CLI that will create a build of our project. We need to do this because our Express server is going to look for a /dist folder to serve the files.

$ ng build

Great! We're only 362 words into this tutorial and we have the Nodejs and Angular portion finished. This leaves Express and MongoDB.

(Step 3) Setting up Express.js

While still inside of the project folder, we're going to use NPM to install a few different packages. Run the following command:

$ npm install express body-parser --save

This will install the Express server package and body-parser, which is a middleware for parsing incoming request bodies. You'll see how it works in a little bit.

Using your preferred code editor (I use Visual Studio Code), open up the project folder and create a new file server.js in the base project folder (mean).

In /server.js paste the following contents:

const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const http = require('http');
const app = express();

// API file for interacting with MongoDB
const api = require('./server/routes/api');

// Parsers
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false}));

// Angular DIST output folder
app.use(express.static(path.join(__dirname, 'dist')));

// API location
app.use('/api', api);

// Send all other requests to the Angular app
app.get('*', (req, res) => {
    res.sendFile(path.join(__dirname, 'dist/index.html'));
});

//Set Port
const port = process.env.PORT || '3000';
app.set('port', port);

const server = http.createServer(app);

server.listen(port, () => console.log(`Running on localhost:${port}`));

I've provided basic comments that describe what's happening above, so I won't bother elaborating on it any further. The above configuration will work for most apps and you shouldn't need to modify it.

(Step 4) Setting up MongoDB

You have two options for setting up a MongoDB. You can either use a DaaS (Database as a Service) like mlab.com, or you can setup your own MongoDB locally & on the production server.

We're going to set one up locally, which means you need to visit the MongoDB Downloads page and choose the appropriate installation package based on your OS. Once you have it installed, you need to visit the MongoDB Installation documentation which will show you the necessary steps for getting MongoDB up and running on your machine.

For instance, on Windows, you have to start MongoDB at the command prompt:

"C:\Program Files\MongoDB\Server\3.4\bin\mongod.exe"

Then, you have to open another command prompt and connect to it through the shell by running:

"C:\Program Files\MongoDB\Server\3.4\bin\mongo.exe"

Once you're in the shell, run the following commands to create a database:

> use mean
> db.users.insert({"name":"John Doe"})

Here, we're creating the database and inserting at least 1 document into it.

Back in the console within the project folder, run the following command:

$ npm install mongodb --save

mongodb is a package that allows us to interact with MongoDB.

Back in the code editor, create the following project structure:

/mean (project folder)
   /server
      /routes

You're creating 2 folders, one as server and the other inside server, which is routes.

Inside of the routes folder, create a new file called api.js. Inside of it, paste the following:

const express = require('express');
const router = express.Router();
const MongoClient = require('mongodb').MongoClient;
const ObjectID = require('mongodb').ObjectID;

// Connect
const connection = (closure) => {
    return MongoClient.connect('mongodb://localhost:27017/mean', (err, db) => {
        if (err) return console.log(err);

        closure(db);
    });
};

// Error handling
const sendError = (err, res) => {
    response.status = 501;
    response.message = typeof err == 'object' ? err.message : err;
    res.status(501).json(response);
};

// Response handling
let response = {
    status: 200,
    data: [],
    message: null
};

// Get users
router.get('/users', (req, res) => {
    connection((db) => {
        db.collection('users')
            .find()
            .toArray()
            .then((users) => {
                response.data = users;
                res.json(response);
            })
            .catch((err) => {
                sendError(err, res);
            });
    });
});

module.exports = router;

Save this. Back in the console, run the following command in the project folder:

$ node server

Then, visit http://localhost:3000/api and with any luck, the output should be:

{"status":200,"users":[{"_id":"598c9da2f7d6d70def3d9f6c","name":"John Doe"}

Great! You can try adding more documents within the collection and refreshing this URL.

Fetching Data from Angular

The last order of business is to display the data that we've retrieved from MongoDB. Right now, we're only accessing it by directly visiting the API endpoint URL, which is useless.

We're going to use the Angular CLI to create a service file for communicating with the API.

$ ng g service data

Open up the new file that was generated /src/app/data.service.ts and paste the following:

import { Injectable } from '@angular/core';

import { Http, Headers, RequestOptions } from '@angular/http';
import 'rxjs/add/operator/map';

@Injectable()
export class DataService {

  result:any;

  constructor(private _http: Http) { }

  getUsers() {
    return this._http.get("/api/users")
      .map(result => this.result = result.json().data);
  }

}

We're importing necessary functions from the http library along with the map operator to handle response data from the API.

We're also delcaring a getUsers() method that communicates with the API endpoint we defined for grabbing all users /api/users. We use the map operator to take the response, which contains our object, and we're grabbing just the .data in json() format.

Before we can use this service file, it has to be provided in our /src/app/app.module.ts file:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';

// Import the Http Module and our Data Service
import { HttpModule } from '@angular/http';
import { DataService } from './data.service';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpModule              // <-Add HttpModule
  ],
  providers: [DataService], // <-Add DataService
  bootstrap: [AppComponent]
})
export class AppModule { }

Now, let's say we want to show all of the users when the app loads. Well, open up /src/app/app.component.ts file and add the following:

import { Component } from '@angular/core';

// Import the DataService
import { DataService } from './data.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  
  // Define a users property to hold our user data
  users: Array<any>;

  // Create an instance of the DataService through dependency injection
  constructor(private _dataService: DataService) {

    // Access the Data Service's getUsers() method we defined
    this._dataService.getUsers()
        .subscribe(res => this.users = res);
  }
}

The last order of business is to modify the /src/app/app.component.html template file:

<h1>Our MongoDB is Working!</h1>

<ul>
  <li *ngFor="let user of users">{{ user.name }}</li>
</ul>

Go back to the console and run ng build to rebuild our modified Angular app.

Then run node server. Visit localhost:3000 in the browser, and with any luck, it should show any of the documents you added through the mongo shell.

Going Further

In a regular CRUD app (Create Read Update Delete), this is simply Read, as we're reading from the database. 

To handling creation, updating and deleting, the steps are as follows:

  1. Modify the /server/routes/api.js to include a new endpoint for either creating, updating or deleting. The syntax is very similar, but you may need to use Google to find examples.
  2. Modify the /src/app/data.service.ts file. You would create a new method for communicating with the API.
  3. Use the new methods in your components.

Troubleshooting

There's a lot of code to work with here, so it's easy to screw something up. If that's the case, you should start with the api.js file by visting the http://localhost:3000/api/endpoint URL. If the response contains the information you want, you're good to go on the API end. If not, you know the problem resides in the API file.

Also, it's important to note, that you must restart the node server command each time you make an update to the API file.

If your problem doesn't reside within the api.js file, then the problem could be within the data.service.ts file, the component that's referencing the desired method, or the template.

Enjoy!


Share this post

Chat with us




Say something about this awesome post!