Angular 5

Angular 5 CRUD Tutorial Example From Scratch


Angular 5 CRUD Tutorial Example From Scratch is today’s leading topic. NodeJS is a platform nowadays because of its features and Express is a web framework build on top of Node.js. Angular CRUD Tutorial is the perfect example of  How to use Angular and Node.js together. We will use MongoDB as a database. It is sort of like MEAN Stack Application. We will cover the detailed tutorial about MEAN Stack in the future. Right now, just CRUD application, we will build.

Angular 5 CRUD Tutorial

First, we need to install the Frontend Framework. So Let’s start with the Installing the Angular Framework. Then we will set up the routing and then we will set the API endpoint to request the server and then query the database according to request and display the information according to it.

Step 1: Install Angular via CLI.

You need to set up a dev environment before you can do anything.
Install Node.js® and npm if they are not already on your machine.
 Then install the Angular CLI globally.
npm install -g @angular/cli

Step 2. Create a new project.

Type the following command. It will create the folder structure and also install the remaining dependencies.
ng new ng5crud

Step 3: Make three components of the application.

Create one directory inside src  >>  app folder called components.
Go to the root of the folder and in the console and hit the following command.
ng g c index
ng g c create
ng g c edit
We have created three components. Each component will do its job. Here we are establishing the single responsibility principle for every component.
It makes a separate folder inside src  >>  app directory. We need to move all these three folders inside components folder.
Also, we need to change the app.module.ts file, to write the correct path of the imported components. By default, it’s an app directory.

Step 4: Routing and Navigation.

The Angular Router enables navigation from one view to the next as users perform application tasks.
First, we need to import the routing modules inside our app.module.ts file.
// app.module.ts

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

imports: [
    BrowserModule, RouterModule
],

Configuration

When we have created the components, it’s by default path is different and now we have moved to the components, so now its path is different. So, first, we need to change that path in app.module.ts file.
Okay, now we need to configure the routes. So make one file inside app directory called routerConfig.ts file.
Write the following code in it.
// routerConfig.ts

import { Routes } from '@angular/router';
import { CreateComponent } from './components/create/create.component';
import { EditComponent } from './components/edit/edit.component';
import { IndexComponent } from './components/index/index.component';

export const appRoutes: Routes = [
  { path: 'create', 
    component: CreateComponent 
  },
  {
    path: 'edit/:id',
    component: EditComponent
  },
  { path: 'index',
    component: IndexComponent
  }
];
We have defined one array, and inside that array, we have registered the different routes with their components. Finally, we have exported it.
Now, import this object inside app.module.ts and register the module.
// app.module.ts

import { appRoutes } from './routerConfig';

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

Step 5: Define the Router outlet.

In the app.component.html file, write the following code.
<div style="text-align:center">
  <h1>
    Welcome to {{title}}!!
  </h1>
  <nav>
    <a routerLink="create" routerLinkActive="active">Add coins</a>
  </nav>
  <router-outlet></router-outlet>
</div>
Also, we need to change the title attribute.
// app.component.ts

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'Welcome to crypto world';
}

Step 6: 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, 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 coins
        </a>
      </li>    
    </ul>
  </div>
</nav>

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

Step 7: Make a form in the create a component file.

First, our create.component.ts file looks like this.
import { Component, OnInit } from '@angular/core';

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

  title = 'Add Coin';
  constructor() { }

  ngOnInit() {
  }

}
And then, we need to make the create.component.html form design.
<div class="panel panel-primary">
    <div class="panel-heading">
      {{ title }}
    </div>
    <div class="panel-body">
      <form>
        <div class="form-group">
          <label class="col-md-4">Coin Name</label>
          <input type="text" class="form-control" name="coin_name"/>
        </div>
        <div class="form-group">
          <label class="col-md-4">Coin Price</label>
          <input type="text" class="form-control" name="coin_price"/>
          </div>
          <div class="form-group">
            <button type="submit" class="btn btn-primary">Add</button>
          </div>
      </form>
    </div>
  </div>
Now, head over to this. http://localhost:4200/create . It looks like this.
Angular CRUD Tutorial

Step 8: Configure HttpClientModule.

Go to the app.module.ts file. Include the HttpClientModule in it.
import {HttpClientModule} from '@angular/common/http';

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

Step 9: Create services to send http requests.

Type the following command in your terminal.
ng g service coin
It will create the following classes.
  1. coin.service.ts
  2. coin.service.spec.ts
Now, import the service file into the app.module.ts file.
import { CoinService } from './coin.service';

providers: [CoinService]

Step 10: Configure Node.js MongoDB backend.

Next step, would be to create Node.js and Express backend to store the data. Create one file in the project root called server.js
Now, we need to install the express framework and other dependencies via NPM, so let us do it first.
npm install --save express body-parser cors mongoose nodemon
Switch to newly created server.js file and enter the following code into it.
// server.js

var 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 the MongoDB database and connect it with our express application.
Note: You need to have installed MongoDB database on your server or local otherwise first you need to download it and start the MongoDB server.
Create one config folder inside project root. In that create one file called DB.js.
// DB.js

module.exports = {
   DB: 'mongodb://localhost:27017/angularcrud'
};
Import this file into our server.js file and use mongoose to set up a database connection with MongoDB. You need to copy the whole server.js file; I am about to show so that nothing will left and lead us to error.
// 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);
       });

Step 11: Create Express routes for our application.

Now, we need to create two folders in a root called expressRoutes and models.
In models folder, create one model called Coin.js.
var mongoose = require('mongoose');
var Schema = mongoose.Schema;

// Define collection and schema for Items
var Coin = new Schema({
  name: {
    type: String
  },
  price: {
    type: Number
  }
},{
    collection: 'coins'
});

module.exports = mongoose.model('Coin', Coin);
In the expressRouter folder, create one file called coinRoutes.js.
// coinRoutes.js

var express = require('express');
var app = express();
var coinRoutes = express.Router();

// Require Item model in our routes module
var Coin = require('../models/Coin');

// Defined store route
coinRoutes.route('/add').post(function (req, res) {
  var coin = new Coin(req.body);
   coin.save()
    .then(item => {
    res.status(200).json({'coin': 'Coin added successfully'});
    })
    .catch(err => {
    res.status(400).send("unable to save to database");
    });
});

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

// Defined edit route
coinRoutes.route('/edit/:id').get(function (req, res) {
  var id = req.params.id;
  Coin.findById(id, function (err, coin){
      res.json(coin);
  });
});

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

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

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

module.exports = coinRoutes;
Here, I have defined all the routes related to CRUD application.
This file will be included in our server.js file.
// server.js

coinRoutes = require('./expressRoutes/coinRoutes');

app.use('/coins', coinRoutes);

Step 12: Insert the value in the MongoDB.

From the front end side, we need to set up HttpClientModule and fire up the HTTP Post call to the NodeJS server.
// server.js

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

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;

app.use('/coins', coinRoutes);

const server = app.listen(port, function(){
  console.log('Listening on port ' + port);
});
We need to include the ReactiveFormsModule in the app.module.ts file.
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { HttpClientModule } from '@angular/common/http';
import { ReactiveFormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { IndexComponent } from './components/index/index.component';
import { CreateComponent } from './components/create/create.component';
import { EditComponent } from './components/edit/edit.component';
import { appRoutes } from './routerConfig';

import { CoinService } from './coin.service';

@NgModule({
  declarations: [
    AppComponent,
    IndexComponent,
    CreateComponent,
    EditComponent
  ],
  imports: [
    BrowserModule, RouterModule.forRoot(appRoutes), HttpClientModule, ReactiveFormsModule
  ],
  providers: [CoinService],
  bootstrap: [AppComponent]
})
export class AppModule { }
Then, we are validating the forms. So first write the form HTML in the create.component.html. 
<div class="panel panel-primary">
    <div class="panel-heading">
      {{ title }}
    </div>
    <div class="panel-body">
      <form [formGroup]="angForm" novalidate>
        <div class="form-group">
          <label class="col-md-4">Coin 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">Coin 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)="addCoin(name.value, price.value)" [disabled]="angForm.pristine || angForm.invalid" class="btn btn-primary">Add</button>
          </div>
      </form>
    </div>
  </div>
Also, we need to write the logic of validation in the create.component.ts file.
// create.component.ts

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

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

  title = 'Add Coin';
  angForm: FormGroup;
  constructor(private coinservice: CoinService, private fb: FormBuilder) {
    this.createForm();
   }
  createForm() {
    this.angForm = this.fb.group({
      name: ['', Validators.required ],
      price: ['', Validators.required ]
   });
  }
  addCoin(name, price) {
      this.coinservice.addCoin(name, price);
  }
  ngOnInit() {
  }
}

MEAN Stack Tutorial With Example From Scratch
Write the coin.service.ts file to insert the data into the database.
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { FormGroup,  FormBuilder,  Validators } from '@angular/forms';

@Injectable()
export class CoinService {

  constructor(private http: HttpClient) { }

  addCoin(name, price) {
    const uri = 'http://localhost:4000/coins/add';
    const obj = {
      name: name,
      price: price
    };
    this.http.post(uri, obj)
        .subscribe(res => console.log('Done'));
  }
}
Start the node.js server by typing: node server. If all the database configuration is right then, you can see the data is inserting into the database.

Step 13: Display the data to the frontend.

In the index.component.html file, write the following code.
<table class="table table-hover">
  <thead>
  <tr>
      <td>Coin Name</td>
      <td>Coin Price</td>
      <td colspan="2">Actions</td>
  </tr>
  </thead>

  <tbody>
      <tr *ngFor="let coin of coins">
          <td>{{ coin.name }}</td>
          <td>{{ coin.price }}</td>
          <td><a [routerLink]="['/edit', coin._id]" class="btn btn-primary">Edit</a></td>
          <td><a routerLink="" class="btn btn-danger">Delete</a></td>
      </tr>
  </tbody>
</table>
Also, you need to update the index.component.ts file and call the service functions to make an http get request.
import { CoinService } from './../../coin.service';
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';

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

  coins: any;

  constructor(private http: HttpClient, private service: CoinService) {}

  ngOnInit() {
    this.getCoins();
  }

  getCoins() {
    this.service.getCoins().subscribe(res => {
      this.coins = res;
    });
  }
}
Write the coin.service.ts file to make an http get request.
import { Injectable } from '@angular/core';
import { FormGroup,  FormBuilder,  Validators } from '@angular/forms';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';

@Injectable()
export class CoinService {

  result: any;
  constructor(private http: HttpClient) {}

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

  getCoins() {
    const uri = 'http://localhost:4000/coins';
    return this
            .http
            .get(uri)
            .map(res => {
              return res;
            });
  }

  editCoin(id) {
    const uri = 'http://localhost:4000/coins/edit/' + id;
    return this
            .http
            .get(uri)
            .map(res => {
              return res;
            });
  }
}
Now, move over to http://localhost:4200/index
It will display the data. Now, we need to add the actions to Edit and Delete.

Step 14: Edit and Delete the Coins.

Now, first, we need to fetch the data from the database and display in the edit form. So first, edit form looks like this. Write the following code in the edit.component.html file.
<div class="panel panel-primary">
  <div class="panel-heading">
    {{ title }}
  </div>
  <div class="panel-body">
    <form [formGroup]="angForm" novalidate>
      <div class="form-group">
        <label class="col-md-4">Coin Name</label>
        <input type="text" class="form-control" formControlName="name" #name [(ngModel)] = "coin.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">Coin Price</label>
        <input type="text" class="form-control" formControlName="price" #price [(ngModel)] = "coin.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)="updateCoin(name.value, price.value)" [disabled]="angForm.pristine || angForm.invalid" class="btn btn-primary">Update</button>
        </div>
    </form>
  </div>
</div>
Okay, next step is code the edit.component.ts file.
// edit.component.ts

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { CoinService } from './../../coin.service';
import { FormGroup,  FormBuilder,  Validators } from '@angular/forms';

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

  coin: any;
  angForm: FormGroup;
  title = 'Edit Coin';
  constructor(private route: ActivatedRoute, private router: Router, private service: CoinService, private fb: FormBuilder) {
    this.createForm();
   }

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

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

  ngOnInit() {
    this.route.params.subscribe(params => {
      this.coin = this.service.editCoin(params['id']).subscribe(res => {
        this.coin = res;
      });
    });
  }
}
Now, also write the code into the coin.service.ts file.
import { Injectable } from '@angular/core';
import { FormGroup,  FormBuilder,  Validators } from '@angular/forms';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';

@Injectable()
export class CoinService {

  result: any;
  constructor(private http: HttpClient) {}

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

  getCoins() {
    const uri = 'http://localhost:4000/coins';
    return this
            .http
            .get(uri)
            .map(res => {
              return res;
            });
  }

  editCoin(id) {
    const uri = 'http://localhost:4000/coins/edit/' + id;
    return this
            .http
            .get(uri)
            .map(res => {
              return res;
            });
  }

  updateCoin(name, price, id) {
    const uri = 'http://localhost:4000/coins/update/' + id;

    const obj = {
      name: name,
      price: price
    };
    this
      .http
      .post(uri, obj)
      .subscribe(res => console.log('Done'));
  }
}
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.
<table class="table table-hover">
  <thead>
  <tr>
      <td>Coin Name</td>
      <td>Coin Price</td>
      <td colspan="2">Actions</td>
  </tr>
  </thead>

  <tbody>
      <tr *ngFor="let coin of coins">
          <td>{{ coin.name }}</td>
          <td>{{ coin.price }}</td>
          <td><a [routerLink]="['/edit', coin._id]" class="btn btn-primary">Edit</a></td>
          <td><button (click)="deleteCoin(coin._id)"  class="btn btn-danger">Delete</button></td>
      </tr>
  </tbody>
</table>
Also, write the deleteCoin() function edit.component.ts file.
deleteCoin(id) {
    this.service.deleteCoin(id).subscribe(res => {
      console.log('Deleted');
    });
}
Finally, whole coin.service.ts file looks like this.
import { Injectable } from '@angular/core';
import { FormGroup,  FormBuilder,  Validators } from '@angular/forms';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';

@Injectable()
export class CoinService {

  result: any;
  constructor(private http: HttpClient) {}

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

  getCoins() {
    const uri = 'http://localhost:4000/coins';
    return this
            .http
            .get(uri)
            .map(res => {
              return res;
            });
  }

  editCoin(id) {
    const uri = 'http://localhost:4000/coins/edit/' + id;
    return this
            .http
            .get(uri)
            .map(res => {
              return res;
            });
  }

  updateCoin(name, price, id) {
    const uri = 'http://localhost:4000/coins/update/' + id;

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

  deleteCoin(id) {
    const uri = 'http://localhost:4000/coins/delete/' + id;

        return this
            .http
            .get(uri)
            .map(res => {
              return res;
            });
  }
}
In this tutorial, I have not done any code that does not prevent the page refresh; You need to refresh the page to see the changes. So I just want you to know that this is how you can write the CRUD application.

Comments

Popular posts from this blog

Angular 4

Difference in Angular 2,4 & 5

Top 15 Best Differences between Angular 4 and Angular 2