Home >>Angular8 Tutorial >Angular8 project
Let's create an Angular 8 project by using the following command:
ng new angular8project
To load bootstrap into your project, use the following command.
npm install bootstrap --save
Now, add the following code inside the angular.json file.
"styles": [ "src/style.css", "./node_modules/bootstrap/dist/css/bootstrap.min.css" ],
Start the Angular development server using the following command.
ng serve -o
We will do a CRUD operation for creating, reading, and updating data. So, we 're going to create 3 components.
To create 3 Angular Components using the following command:
ng g c product-add --skipTests=true ng g c product-get --skipTests=true ng g c product-edit --skipTests=true
Inside the src > > app folder in your project file you can check the app-routing.module.ts file. It's generated because we require angular cli to produce the routing file for us when we install an angular app.
Now, write the following code inside an app-routing.module.ts file:
// app-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { ProductAddComponent } from './product-add/product-add.component';
import { ProductEditComponent } from './product-edit/product-edit.component';
import { ProductGetComponent } from './product-get/product-get.component';
const routes: Routes = [
{
path: 'product/create',
component: ProductAddComponent
},
{
path: 'edit/:id',
component: ProductEditComponent
},
{
path: 'products',
component: ProductGetComponent
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Now you can see that directive is inside the app.component.html file. This directive helps us to render the various component based on the URI of route.
Write the following code inside the app.component.html file.
<nav class="navbar navbar-expand-sm bg-light">
<div class="container-fluid">
<ul class="navbar-nav">
<li class="nav-item">
<a routerLink="product/create" class="nav-link" routerLinkActive="active">
Product
</a>
</li>
<li class="nav-item">
<a routerLink="products" class="nav-link" routerLinkActive="active">
Link
</a>
</li>
</ul>
</div>
</nav>
<div class="container">
<router-outlet></router-outlet>
</div>
Type the following command to install the ng2-slim-loading-bar library.
npm install ng2-slim-loading-bar --save
If you have third party packages installed right now, then Angular 8 is not compatible. You will need to install the following library to solve the problem between Angular 8 and third-party packages.
npm install rxjs-compat --save
Now, import the SlimLoadingBarModule inside an app.module.ts file.
import { SlimLoadingBarModule } from 'ng2-slim-loading-bar';
imports: [
...
SlimLoadingBarModule
],
Now, include the styling that comes with the library inside src >> styles.css file.
@import "../node_modules/ng2-slim-loading-bar/style.css";
Now, write the following code inside the app.component.ts file.
import { Component } from '@angular/core';
import {SlimLoadingBarService} from 'ng2-slim-loading-bar';
import { NavigationCancel,
Event,
NavigationEnd,
NavigationError,
NavigationStart,
Router } from '@angular/router';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'Angular 8';
constructor(private loadingBar: SlimLoadingBarService, private router: Router) {
this.router.events.subscribe((event: Event) => {
this.navigationInterceptor(event);
});
}
private navigationInterceptor(event: Event): void {
if (event instanceof NavigationStart) {
this.loadingBar.start();
}
if (event instanceof NavigationEnd) {
this.loadingBar.complete();
}
if (event instanceof NavigationCancel) {
this.loadingBar.stop();
}
if (event instanceof NavigationError) {
this.loadingBar.stop();
}
}
}
In the code above, in Angular application we have specified that if the user navigates from one component to another component, the progress result will be shown.
When the user clicks the other route, the angular progress indicator starts displaying and when the navigation is complete, the display will simply stop. So, for the user this is kind of UX.
The above code intercepts the routing event and applies the loading bar element to each path, so that every time we change routes we can see the routing sign.
Inside the app.component.html file at the top of the page we must add the ng2-slim-loading-bar directive.
<!-- app.component.html --> <ng2-slim-loading-bar color="red"></ng2-slim-loading-bar> <nav class="navbar navbar-expand-sm bg-dark"> <div class="container-fluid"> <ul class="navbar-nav"> <li class="nav-item"> <a routerLink="product/create" class="nav-link" routerLinkActive="active"> Product </a> </li> <li class="nav-item"> <a routerLink="products" class="nav-link" routerLinkActive="active"> Link </a> </li> </ul> </div> </nav> <div class="container"> <router-outlet></router-outlet> </div>
Add the following bootstrap 4 form Inside the product-add.component.html file.
<div class="card">
<div class="card-body">
<form>
<div class="form-group">
<label class="col-md-4">TOPIC</label>
<input type="text" class="form-control" />
</div>
<div class="form-group">
<label class="col-md-4">ONE </label>
<textarea class="form-control" rows = 7 cols = "5"></textarea>
</div>
<div class="form-group">
<label class="col-md-4">TWO</label>
<input type="text" class="form-control" />
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Click me</button>
</div>
</form>
</div>
</div>
import { ReactiveFormsModule } from '@angular/forms';
imports: [
...
ReactiveFormsModule
],
You need to remember that this is not a template-driven type here, and you need to modify the app.component.ts file.
Here, we have to import from @angular / forms the FormGroup, FormBuilder, Validators modules, and build a constructor and instance the FormBuilder.
So, within the product-add.component.ts file, write the following code.
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
@Component({
selector: 'app-product-add',
templateUrl: './product-add.component.html',
styleUrls: ['./product-add.component.css']
})
export class ProductAddComponent implements OnInit {
angForm: FormGroup;
constructor(private fb: FormBuilder) {
this.createForm();
}
createForm() {
this.angForm = this.fb.group({
PN: ['', Validators.required ],
PD: ['', Validators.required ],
PP: ['', Validators.required ]
});
}
ngOnInit() {
}
}
Here we use form builder to manage the whole validation process. Now, we have to create a form with the validation rules in that constructor. There are three fields, in our example. If the text input is empty, otherwise an error may arise and we need to show the error.
Now write the code below within the file product-add.component.html.
To connect with the backend services, Front-end applications often need HTTP protocol. Modern browsers support two separate HTTP request-making APIs: the javaHttpRequest interface, and the fetch (API).
Import in an app.module.ts package the HttpClientModule.
// app.module.ts
import { HttpClientModule } from '@angular/common/http';
imports: [
...
HttpClientModule
],
Inside the src >> app folder, create one file called Product.ts and add the following code.
export default class Product
{
PN: string;
PD: string;
PP: number;
}
Type the following command to generate the service file.
ng g service products --skipTests=true
After creation, it will look like this:
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class ProductsService {
constructor() { }
}
Now, import the products.service.ts file into the app.module.ts file.
import { ProductsService } from './products.service';
providers: [ ProductsService ],
Now we have to write the code that will send the request for HTTP POST with the data to the server Node.js and then save the data to the database MongoDB.
Write the code below within the product.service.ts file.
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class ProductsService {
uri = 'http://localhost:4000/products';
constructor(private http: HttpClient) { }
addProduct(PN, PD, PP) {
const obj = {
PN,
PD,
PP
};
console.log(obj);
this.http.post(`${this.uri}/add`, obj)
.subscribe(res => console.log('Done'));
}
}
Now, we need to attach the click event to the Product Add button. Thus, within the product-add.component.html file add the following files.
<div class="form-group">
<button (click) = "addProduct(PN.value, PD.value, PP.value)" type="submit" class="btn btn-primary"
[disabled]="angForm.pristine || angForm.invalid" >
Product
</button>
</div>
Now within the product-add.component.ts package, apply the feature addProduct). So, within the product-add.component.ts file, write the following code.
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { ProductsService } from '../products.service';
@Component({
selector: 'app-product-add',
templateUrl: './product-add.component.html',
styleUrls: ['./product-add.component.css']
})
export class ProductAddComponent implements OnInit {
angForm: FormGroup;
constructor(private fb: FormBuilder, private ps: ProductsService) {
this.createForm();
}
createForm() {
this.angForm = this.fb.group({
PN: ['', Validators.required ],
PD: ['', Validators.required ],
PP: ['', Validators.required ]
});
}
addProduct(PN, PD, PP) {
this.ps.addProduct(PN, PD, PP);
}
ngOnInit() {
}
}
Create a folder in an angular root folder called the api, and go inside that folder. It would be the entire project, apart from the Angular version. Therefore the directories node modules are separate from those of the Angular project.
Open the terminal in the api folder, and type the command below. Using NPM it will create the package.json file.
Install the following node specific modules.
npm install express body-parser cors mongoose –save
Install the nodemon server and it should make it easy for you not to launch node service if you adjust it. It immediately restarts node.js server.
npm install nodemon --save-dev
const express = require('express'),
path = require('path'),
bodyParser = require('body-parser'),
cors = require('cors'),
mongoose = require('mongoose');
const app = express();
let port = process.env.PORT || 4000;
const server = app.listen(function(){
console.log('Listening on port ' + port);
});
Now, connect our node express application to the MongoDB database.
If you have not installed a MongoDB database then install it and then use the following command to start the Mongodb server.
mongod
Now, we have connected to the database.
Create one file called DB.js inside the api root project folder. Write the following code inside a DB.js file.
module.exports = { DB: 'mongodb://localhost:27017/ng8crud' };
Import this DB.js file into our server.js file, and use the mongoose module to set up the MongoDB database connection. To connect our MongoDB application to the Node.js api, write the following code within the server.js server.
const express = require('express'),
path = require('path'),
bodyParser = require('body-parser'),
cors = require('cors'),
mongoose = require('mongoose'),
config = require('./DB');
mongoose.Promise = global.Promise;
mongoose.connect(config.DB, { useNewUrlParser: true }).then(
() => {console.log('Connected') },
err => { console.log('Not connect'+ 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 this server.js file and go to the terminal and start the node server using the following command.
npm start
So, right now, there are three servers running:
Node.js Server
Angular Development Server
MongoDB server
We now need to build two directories inside the api root folder called routes and models.
Let's build a model in models folder named Product.js with the following code.
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// Define collection and schema for Product
let Product = new Schema({
ProductName: {
type: String
},
ProductDescription: {
type: String
},
ProductPrice: {
type: Number
}
},{
collection: 'Product'
});
module.exports = mongoose.model('Product', Product);
We have established our Product Selection scheme here. We have three fields called ProductName, DescriptionProduct, ProductPrice.
Create one file named product.route.js in the routes folder.
Inside the product.route.js file write the following CRUD code.