Angular 6 CRUD Example Tutorial From Scratch

Hello coders, In this tutorial, I will show you a demo code about Angular 6 CRUD Example Tutorial From Scratch. Angular 6 Stable is released some days ago, and now it is the time to create a demo application using Angular 6. You can find more about Angular 6 on their official documentation.

What will we build?

After this tutorial, we will be able to understand how Angular Router, Components, and HTTP request works.  We build a fully functional CRUD application in Angular 6. So it is straightforward to follow as well.

Angular 6 CRUD Example Tutorial

We will start our tutorial by installing the Angular 6 using the Angular CLI.

Quick note: You have already installed Node.js on your machine. Otherwise first install it and then continue here.

#1: Install Angular 6 using Angular CLI.

Install Angular CLI globally on your machine using the following command.

npm install -g @angular/cli

If above command installation fails then, please run the above command in administrator mode.

Now, create a local project using the following command.

ng new angular6crud

Now, start the application using the following command.

ng serve --open

It compiles and opens up the browser at this URL: http://localhost:4200

#2: Create three components.

First, create one folder called components inside app folder.

We can create our components using the following command.

Angular 6 CRUD Example Tutorial From Scratch

 

All the components are created inside components folder.

The app.module.ts file will be automatically updated.

#3: Configure the routing.

Inside app.module.ts file, create one array called routes and then add the object that contains route path and route component. Also, import the RouterModule and Routes component.

// app.module.ts

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

const routes:Routes = [
  { 
    path: 'create', 
    component: CreateComponent 
  },
  {
    path: 'edit/:id',
    component: EditComponent
  },
  { 
    path: 'index',
    component: IndexComponent
  }
]

Now, register these routes.

// app.module.ts

imports: [
    BrowserModule,
    RouterModule.forRoot(routes)
],

Now, we can include the <router-outlet> inside an app.component.html file.

<div>
  <router-outlet></router-outlet>
</div>

Now, you can see the components based on routes.

For example, if you browse http://localhost:4200/create then you can see “create works!” in your browser.

#4: Add Bootstrap CSS.

Download the bootstrap from its original docs and paste the CSS and JS folders inside src  >>  assets folder.

In the src >>  index.html file, add the bootstrap css file.

<link rel="stylesheet" href="assets/css/bootstrap.min.css">

Also, add the navigation and change the app.component.html outlook due to bootstrap classes.

<nav class="navbar navbar-default">
  <div class="container-fluid">
    <ul class="nav navbar-nav">
      <li class="active">
        <a routerLink="create" routerLinkActive="active">
          Add Games
        </a>
      </li>    
    </ul>
  </div>
</nav>

<div class="container">
  <router-outlet></router-outlet>
</div>

#5: Make a form in the create a component file.

Inside create.component.html file, write the following command.

<div class="card">
    <div class="card-body">
      <form>
        <div class="form-group">
          <label class="col-md-4">Game Name</label>
          <input type="text" class="form-control" name="game_name"/>
        </div>
        <div class="form-group">
          <label class="col-md-4">Game Price</label>
          <input type="text" class="form-control" name="game_price"/>
          </div>
          <div class="form-group">
            <button type="submit" class="btn btn-primary">Add</button>
          </div>
      </form>
    </div>
  </div>

So your create game form looks like this.

Angular 6 Tutorial

 

#6: Configure HttpClientModule.

Go to the app.module.ts file. Include the HttpClientModule in it.

// app.module.ts

import {HttpClientModule} from '@angular/common/http';

imports: [
    BrowserModule, RouterModule.forRoot(appRoutes), HttpClientModule
],

#7: Create services to send http requests.

Type the following command in your terminal.

ng g service game

It will create the following classes.

  1. game.service.ts
  2. game.service.spec.ts

So, your basic game.service.ts file looks like this.

// GameService.ts

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

@Injectable({
  providedIn: 'root'
})
export class GameService {

  constructor() { }
}

Now, import the game.service.ts file into the app.module.ts file.

// game.service.ts

import { GameService } from './game.service';

providers: [ GameService ]

#8: Configure Node.js backend.

Next step, will be to create Node.js and MongoDB backend to store the data. Create one file in the project root called server.js

Now, we need to install the express web framework and other dependencies via NPM, so let us do it first.

npm install --save express body-parser cors mongoose

Also, we need to add nodemon server as a development dependency.

npm install nodemon --save-dev

Switch to newly created server.js file and enter the following code into it.

// app.js

let express = require('express'),
	path = require('path'),
	bodyParser = require('body-parser'),
	cors = require('cors'),
	mongoose = require('mongoose');

	const app = express();
	var port = process.env.PORT || 4000;

	var server = app.listen(function(){
		console.log('Listening on port ' + port);
	});

Next thing is we need to create a MongoDB database and connect it with our node.js application.

If you have not installed the MongoDB database then install it and then start the mongodb server.

Mongodb database

Create one config folder inside project root. In that create one file called DB.js.

// DB.js

module.exports = {
   DB: 'mongodb://localhost:27017/angular6crud'
};

Import this DB.js file into our server.js file and use mongoose library to set up the database connection with MongoDB

Write the following code inside the server.js file to connect our MongoDB application to the Node.js server.

// server.js

const express = require('express'),
	path = require('path'),
	bodyParser = require('body-parser'),
	cors = require('cors'),
	mongoose = require('mongoose'),
	config = require('./config/DB');

	mongoose.Promise = global.Promise;
	mongoose.connect(config.DB).then(
	  () => {console.log('Database is connected') },
	  err => { console.log('Can not connect to the database'+ err)}
	);

	const app = express();
	app.use(bodyParser.json());
	app.use(cors());
	const port = process.env.PORT || 4000;

	const server = app.listen(port, function(){
	 console.log('Listening on port ' + port);
	});

Save the file and go to the cmd and start the node.js server using the following command.

nodemon server

node mongodb connect

Now, We have total three servers are running.

  1. Angular Development Server.
  2. Node.js Server
  3. Mongodb Server

#9: Create Express routes for our application.

Now, we need to create two folders in a root called routes and models.

In models folder, create one model called Game.js.

// Game.js

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

// Define collection and schema for Games
let Game = new Schema({
  name: {
    type: String
  },
  price: {
    type: Number
  }
},{
    collection: 'games'
});

module.exports = mongoose.model('Game', Game);

In the routes folder, create one file called game.route.js.

// game.route.js

const express = require('express');
const app = express();
const gameRoutes = express.Router();

// Require Game model in our routes module
let Game = require('../models/Game');

// Defined store route
gameRoutes.route('/add').post(function (req, res) {
  let game = new Game(req.body);
   game.save()
    .then(game => {
    res.status(200).json({'game': 'CoGamein added successfully'});
    })
    .catch(err => {
    res.status(400).send("unable to save to database");
    });
});

// Defined get data(index or listing) route
gameRoutes.route('/').get(function (req, res) {
   Game.find(function (err, games){
    if(err){
      console.log(err);
    }
    else {
      res.json(games);
    }
  });
});

// Defined edit route
gameRoutes.route('/edit/:id').get(function (req, res) {
  let id = req.params.id;
  Game.findById(id, function (err, game){
      res.json(game);
  });
});

//  Defined update route
gameRoutes.route('/update/:id').post(function (req, res) {
   Game.findById(req.params.id, function(err, game) {
    if (!game)
      return next(new Error('Could not load Document'));
    else {
      game.name = req.body.name;
      game.price = req.body.price;

      game.save().then(game => {
          res.json('Update complete');
      })
      .catch(err => {
            res.status(400).send("unable to update the database");
      });
    }
  });
});

// Defined delete | remove | destroy route
gameRoutes.route('/delete/:id').get(function (req, res) {
   Game.findByIdAndRemove({_id: req.params.id}, function(err, game){
        if(err) res.json(err);
        else res.json('Successfully removed');
    });
});

module.exports = gameRoutes;

I have written all the logic that can create, read, update, and delete the data from the mongodb database.

Include this Game.js model inside a server.js file.

// server.js

const gameRoutes = require('./routes/game.route');

app.use('/games', gameRoutes);

So, our final server.js file looks like this.

// server.js

const express = require('express'),
	path = require('path'),
	bodyParser = require('body-parser'),
	cors = require('cors'),
	mongoose = require('mongoose'),
	config = require('./config/DB');

const gameRoutes = require('./routes/game.route');

	mongoose.Promise = global.Promise;
	mongoose.connect(config.DB).then(
	  () => {console.log('Database is connected') },
	  err => { console.log('Can not connect to the database'+ err)}
	);

const app = express();
	app.use(bodyParser.json());
	app.use(cors());
	app.use('/games', gameRoutes);

const port = process.env.PORT || 4000;

const server = app.listen(port, function(){
	console.log('Listening on port ' + port);
});

#10 Add ReactiveFormsModule at the Angular.

Inside app.module.ts file, add the ReactiveFormsModule from @angular/forms package.

// app.module.ts

import { ReactiveFormsModule } from '@angular/forms';

imports: [
    ReactiveFormsModule
  ],

Then, we are validating the forms. So first write the form HTML in the create.component.html. 

<div class="card">
    <div class="card-body">
      <form [formGroup]="angForm" novalidate>
        <div class="form-group">
          <label class="col-md-4">Game Name</label>
          <input type="text" class="form-control" formControlName="name" #name />
        </div>
        <div *ngIf="angForm.controls['name'].invalid && (angForm.controls['name'].dirty || angForm.controls['name'].touched)" class="alert alert-danger">
          <div *ngIf="angForm.controls['name'].errors.required">
            Name is required.
          </div>
        </div>
        <div class="form-group">
          <label class="col-md-4">Game Price</label>
          <input type="text" class="form-control" formControlName="price" #price/>
        </div>
        <div *ngIf="angForm.controls['price'].invalid && (angForm.controls['price'].dirty || angForm.controls['price'].touched)" class="alert alert-danger">
          <div *ngIf="angForm.controls['price'].errors.required">
            Price is required.
          </div>
        </div>
          <div class="form-group">
            <button (click)="addGame(name.value, price.value)" [disabled]="angForm.pristine || angForm.invalid" class="btn btn-primary">Add</button>
          </div>
      </form>
    </div>
  </div>

Also, we need to write logic of the validation in the create.component.ts file.

// create.component.ts

import { Component, OnInit } from '@angular/core';
import { FormGroup,  FormBuilder,  Validators } from '@angular/forms';
import { GameService } from '../../game.service';

@Component({
  selector: 'app-create',
  templateUrl: './create.component.html',
  styleUrls: ['./create.component.css']
})
export class CreateComponent implements OnInit {

 title = 'Add Game';
  angForm: FormGroup;

  constructor(private gameservice: GameService, private fb: FormBuilder) {
    this.createForm();
   }

   createForm() {
    this.angForm = this.fb.group({
      name: ['', Validators.required ],
      price: ['', Validators.required ]
   });
  }

  addGame(name, price) {
      this.gameservice.addGame(name, price);
  }

  ngOnInit() {
  }

}

Here, till now, we have used the addGame() function, but not created inside game.service.ts file.

So, let us create that.

// game.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class GameService {

  constructor(private http: HttpClient) { }

  addGame(name, price) {
    const uri = 'http://localhost:4000/games/add';
    const obj = {
      name: name,
      price: price
    };
    this.http.post(uri, obj)
        .subscribe(res => console.log('Done'));
  }
}

In this function, we have sent the HTTP Post request to the Node.js server and try to save the values in the database. Now, go to the following URL: http://localhost:4200/create.

Angular 6 Node Tutorial

So, in the after submitting the form, we can see in the console that, we get the “Done.”

MongoDB insert data

 

So, in the database, we can see that our value is inserted correctly.

#10: Display the data to the frontend.

In the index.component.html file, write the following code.

<table class="table table-hover">
  <thead>
  <tr>
      <td>Game Name</td>
      <td>Game Price</td>
      <td colspan="2">Actions</td>
  </tr>
  </thead>

  <tbody>
      <tr *ngFor="let game of games">
          <td>{{ game.name }}</td>
          <td>{{ game.price }}</td>
          <td><a [routerLink]="['/edit', game._id]" class="btn btn-primary">Edit</a></td>
          <td><a [routerLink]="" class="btn btn-danger">Delete</a></td>
      </tr>
  </tbody>
</table>

Now, inside index folder, create one file called Game.ts. It is an interface, which tells the Angular application that, which kind of data is on the backend that we need to display at frontend.

// Game.ts

export interface Game {
    id: Number;
    name: String;
    price: Number;
}

Now, inside game.service.ts file, we need to write a function that fetches the data from the MongoDB database and display at the Angular 6 Application.

// game.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Game } from './components/index/Game';

@Injectable({
  providedIn: 'root'
})
export class GameService {

	const uri = 'http://localhost:4000';

 	constructor(private http: HttpClient) { }

  	addGame(name, price) {
	    const obj = {
	      name: name,
	      price: price
	    };
	    this
	    	.http
	    	.post(`${this.uri}/games/add`, obj)
	        .subscribe(res => 
	        	console.log('Done')
	        );
  	}

  	getGames() {
             return this
                    .http
                    .get(`${this.uri}/games`);
    	}
 }
}

Moreover, finally, we need to update the index.component.ts file.

// index.component.ts

import { Component, OnInit } from '@angular/core';
import { Game } from './Game';
import { GameService } from '../../game.service';

@Component({
  selector: 'app-index',
  templateUrl: './index.component.html',
  styleUrls: ['./index.component.css']
})
export class IndexComponent implements OnInit {

	games: Game[];

 	constructor(private gameservice: GameService) { }

  	ngOnInit() {
  		this.gameservice
      		.getGames()
      		.subscribe((data: User[]) => {
        		this.games = data;
        });
    }
}

Now, add one more data into the database and switch to this URL: http://localhost:4200/index.

Angular 6 Node MongoDB CRUD

#11: Edit and Update the Data.

Now, first, we need to fetch the data from the MongoDB database based on a _id, display the data in the edit form.

So first, edit.component.html form looks like this. 

Write the following code inside an edit.component.html file.

<div class="card">
    <div class="card-body">
      <form [formGroup]="angForm" novalidate>
        <div class="form-group">
          <label class="col-md-4">Game Name</label>
          <input type="text" class="form-control" formControlName="name" #name [(ngModel)] = "game.name"/>
        </div>
        <div *ngIf="angForm.controls['name'].invalid && (angForm.controls['name'].dirty || angForm.controls['name'].touched)" class="alert alert-danger">
          <div *ngIf="angForm.controls['name'].errors.required">
            Name is required.
          </div>
        </div>
        <div class="form-group">
          <label class="col-md-4">Game Price</label>
          <input type="text" class="form-control" formControlName="price" #price [(ngModel)] = "game.price"/>
        </div>
        <div *ngIf="angForm.controls['price'].invalid && (angForm.controls['price'].dirty || angForm.controls['price'].touched)" class="alert alert-danger">
          <div *ngIf="angForm.controls['price'].errors.required">
            Price is required.
          </div>
        </div>
          <div class="form-group">
            <button (click)="updateGame(name.value, price.value)" [disabled]="angForm.pristine || angForm.invalid" class="btn btn-primary">Add</button>
          </div>
      </form>
    </div>
  </div>

Inside edit.component.ts file, write the following code.

// edit.component.ts

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { FormGroup,  FormBuilder,  Validators } from '@angular/forms';
import { GameService } from '../../game.service';
import { Game } from '../index/Game';

@Component({
  selector: 'app-edit',
  templateUrl: './edit.component.html',
  styleUrls: ['./edit.component.css']
})
export class EditComponent implements OnInit {

	game: any = {};
	angForm: FormGroup;
	constructor(private route: ActivatedRoute, 
				private router: Router, 
				private service: GameService, 
				private fb: FormBuilder) { 
		this.createForm();
	}

	createForm() {
    this.angForm = this.fb.group({
	     	name: ['', Validators.required ],
	      	price: ['', Validators.required ]
   		});
  	}

	ngOnInit() {
		this.route.params.subscribe(params => {
     		this.service.editGame(params['id']).subscribe(res => {
        		this.game = res;
      	});
    });
  }
}
// edit.component.ts

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { FormGroup,  FormBuilder,  Validators } from '@angular/forms';
import { GameService } from '../../game.service';
import { Game } from '../index/Game';

@Component({
  selector: 'app-edit',
  templateUrl: './edit.component.html',
  styleUrls: ['./edit.component.css']
})
export class EditComponent implements OnInit {

	game: any = {};
	angForm: FormGroup;
	constructor(private route: ActivatedRoute, 
		    private router: Router, 
		    private service: GameService, 
		    private fb: FormBuilder) { 
	    this.createForm();
	}

	createForm() {
                   this.angForm = this.fb.group({
	     	name: ['', Validators.required ],
	      	price: ['', Validators.required ]
   	     });
  	}

	ngOnInit() {
		this.route.params.subscribe(params => {
     		this.service.editGame(params['id']).subscribe(res => {
        		this.game = res;
      	});
    });
  }
}

Finally, our game.service.ts file looks like this.

// game.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Game } from './components/index/Game';

@Injectable({
  providedIn: 'root'
})
export class GameService {

	uri = 'http://localhost:4000/games';

 	constructor(private http: HttpClient) { }

  	addGame(name, price) {
	    const obj = {
	      name: name,
	      price: price
	    };
	    this
	    	.http
	    	.post(`${this.uri}/add`, obj)
	        .subscribe(res => 
	        	console.log('Done')
	        );
  	}

  	getGames() {
  		return this
            .http
            .get(`${this.uri}`);
    }

    editGame(id) {
    	return this
            .http
            .get(`${this.uri}/edit/${id}`)
    	}
 }

Below image is our Edit layout.

Angular 6 Edit Tutorial

 

Now, update the data. So write the following code inside game.service.ts file. We will write the update function inside game.service.ts file.

// game.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Game } from './components/index/Game';

@Injectable({
  providedIn: 'root'
})
export class GameService {

  uri: String = 'http://localhost:4000/games';

  constructor(private http: HttpClient) { }

  addGame(name, price) {
	    const obj = {
	      name: name,
	      price: price
	    };
	    this
	    	.http
	    	.post(`${this.uri}/add`, obj)
	        .subscribe(res => 
	        	console.log('Done')
	        );
  	}

  getGames() {
  	return this
            .http
            .get(`${this.uri}`);
    }

   editGame(id) {
    	return this
            .http
            .get(`${this.uri}/edit/${id}`)
    	}

   updateGame(name, price, id) {

      const obj = {
	  name: name,
	   price: price
       };
	this
	   .http
	   .post(`${this.uri}/update/${id}`, obj)
	   .subscribe(res => console.log('Done'));
  	}
}

Now, write the following code inside edit.component.ts file.

// edit.component.ts

updateGame(name, price) {
     this.route.params.subscribe(params => {
     this.service.updateGame(name, price, params['id']);
     this.router.navigate(['index']);
  });
}

So, if you find no error on the console, then you can successfully update the data.

 I have already written edit and update service to make an API call. So till now, Create, Read, Update is complete. Now, take a look at Delete.

Now, I am coding the whole index.component.html file.

<tbody>
      <tr *ngFor="let game of games">
          <td>{{ game.name }}</td>
          <td>{{ game.price }}</td>
          <td><a [routerLink]="['/edit', game._id]" class="btn btn-primary">Edit</a></td>
          <td><button (click)="deleteGame(game._id)"  class="btn btn-danger">Delete</button></td>
      </tr>
</tbody>

Now, write the deleteGame function inside index.component.tfile.

// index.component.ts

import { Component, OnInit } from '@angular/core';
import { Game } from './Game';
import { GameService } from '../../game.service';

@Component({
  selector: 'app-index',
  templateUrl: './index.component.html',
  styleUrls: ['./index.component.css']
})
export class IndexComponent implements OnInit {

    games: Game[];

    constructor(private gameservice: GameService) { }

    ngOnInit() {
  	this.gameservice
      	    .getGames()
      	    .subscribe((data: Game[]) => {
        	this.games = data;
        });
   }

   deleteGame(id) {
     this.gameservice.deleteGame(id).subscribe(res => {
      console.log('Deleted');
    });
   }
}

Finally, write the deleteGame function inside game.service.ts file.

// game.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Game } from './components/index/Game';

@Injectable({
  providedIn: 'root'
})
export class GameService {

	uri: String = 'http://localhost:4000/games';

 	constructor(private http: HttpClient) { }

  	addGame(name, price) {
	    const obj = {
	      name: name,
	      price: price
	    };
	    this
	    	.http
	    	.post(`${this.uri}/add`, obj)
	        .subscribe(res => 
	        	console.log('Done')
	        );
  	}

  	getGames() {
  		return this
            .http
            .get(`${this.uri}`);
    }

    editGame(id) {
    	return this
            .http
            .get(`${this.uri}/edit/${id}`)
    	}

 	updateGame(name, price, id) {

		const obj = {
			name: name,
			price: price
	    };
	    this
	    	.http
	    	.post(`${this.uri}/update/${id}`, obj)
	     	.subscribe(res => console.log('Done'));
  	}

  	deleteGame(id) {
  		return this
            .http
            .get(`${this.uri}/delete/${id}`)
  	}
}

I have written the whole file and finally our Angular 6 CRUD Example Tutorial is over.

If you have any doubt in Angular 6 CRUD Example Tutorial, then ask in a comment below.

Github Code

Post Your Thoughts

This site uses Akismet to reduce spam. Learn how your comment data is processed.

18 Comments