The First Component - App Component How Each Component (Or Its Category) Corresponds To A Physical Folder See
The First Component - App Component How Each Component (Or Its Category) Corresponds To A Physical Folder See
The First Component - App Component How Each Component (Or Its Category) Corresponds To A Physical Folder See
Component
Angular 7 got released this October and here is an Angular 7 full stack App example with Spring Boot.
In my last examples of angular, we had covered many topics on angular such as Spring Boot Angular Example, Angular JWT
Authentication and Material Design with Angular and many more and in due course we had exposed some REST APIs to be consumed by
the angular client. Hence, we will be using the same set of APIs here for the CRUD operation while building our Angular 6 app. Later, in the
article I will be providing the API details. But for now, here is the spring controller class for the same on github.
Angular v6 is the first release of Angular that unifies the Framework, Material and CLI. @angular/core now depends on.
TypeScript 2.7
RxJS 6.0.0
tslib 1.9.0
Both the CLI and generated project have dependencies that require Node 8.9 or higher, together with NPM 5.5.1 or higher. For this project,
I have npm 5.6.0 and node v8.11.2 installed on my local system. You can download the latest version of Node js from here -Node Js
Official. To update NPM, you can run the following command in the terminal.
npm i npm@latest -g
If u have an @angular/cli version older then 6, then run following command to install the latest versions:
Once, the npm and node is upgraded to the latest version, you can run following command to
generate angular 6 project in any location of your choice.
ng new angular6-example
Doing so, our angular 6 application is generated with TypeScript 2.7 & RxJS 6.RxJS 6 contains some
breaking changes and hence a new package, rxjs-compat, can be installed alongside RxJS 6 to
provide a compatibility layer while upgrading your code to the new syntax.
cd angular6-example
ng serve
As discussed above, we will have multiple components such as login and add-user,
edit-user, create-user. Once an admin login successfully, he can perform user CRUD
operation.Following are the commands to generate our components.
ng g component login
ng g component add-user
ng g component edit-user
ng g component list-user
Angular 6 Routing
Following is our routing configuration.We have configured to use LoginComponent
as a default component.Also, do not forget to include it in the main module
- app.module.ts
app.routing.ts
import { RouterModule, Routes } from '@angular/router';
import {LoginComponent} from "./login/login.component" ;
import {AddUserComponent} from "./add-user/add-user.component" ;
import {ListUserComponent} from "./list-user/list-user.component" ;
import {EditUserComponent} from "./edit-user/edit-user.component" ;
const routes: Routes = [
{ path: 'login', component: LoginComponent },
{ path: 'add-user', component: AddUserComponent },
{ path: 'list-user', component: ListUserComponent },
{ path: 'edit-user', component: EditUserComponent },
{path : '', component : LoginComponent}
];
export const routing = RouterModule.forRoot(routes);
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { LoginComponent } from './login/login.component';
import {routing} from "./app.routing";
import {AuthenticationService} from "./service/auth.service";
import {ReactiveFormsModule} from "@angular/forms";
import {HttpClientModule} from "@angular/common/http";
import { AddUserComponent } from './add-user/add-user.component' ;
import { EditUserComponent } from './edit-user/edit-user.component' ;
import {ListUserComponent} from "./list-user/list-user.component" ;
import {UserService} from "./service/user.service" ;
@NgModule({
declarations: [
AppComponent,
LoginComponent,
ListUserComponent,
AddUserComponent,
EditUserComponent
],
imports: [
BrowserModule,
routing,
ReactiveFormsModule,
HttpClientModule
],
providers: [AuthenticationService, UserService],
bootstrap: [AppComponent]
})export class AppModule { }
getUsers() {
return this.http.get<User[]>(this.baseUrl);
}
getUserById(id: number) {
return this.http.get<User>(this.baseUrl + '/' + id);
}
createUser(user: User) {
return this.http.post(this.baseUrl, user);
}
updateUser(user: User) {
return this.http.put(this.baseUrl + '/' + user.id, user);
}
deleteUser(id: number) {
return this.http.delete(this.baseUrl + '/' + id);
}
}
login.component.html
<div class="row">
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
loginForm: FormGroup;
submitted: boolean = false;
invalidLogin: boolean = false;
constructor(private formBuilder: FormBuilder, private router: Router, private
authService: AuthenticationService) { }
onSubmit() {
this.submitted = true;
if (this.loginForm.invalid) {
return;
}
if(this.loginForm.controls.email.value == '[email protected]' &&
this.loginForm.controls.password.value == 'password') {
this.router.navigate(['list-user']);
}else {
this.invalidLogin = true;
}
}
ngOnInit() {
this.loginForm = this.formBuilder.group({
email: ['', Validators.required],
password: ['', Validators.required]
});
}
Following is list-user.component.html.
<div class="col-md-6">
<h2> User Details</h2>
<button class="btn btn-danger" (click)="addUser()"> Add User</button>
<table class="table table-striped">
<thead>
<tr>
<th class="hidden">Id</th>
<th>FirstName</th>
<th>LastName</th>
<th>Email</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let user of users">
<td class="hidden"></td>
<td></td>
<td></td>
<td></td>
<td><button class="btn btn-danger" (click)="deleteUser(user)">
Delete</button>
<button class="btn btn-danger" (click)="editUser(user)" style="margin-
left: 20px;"> Edit</button></td>
</tr>
</tbody>
</table>
</div>
list-user.component.ts
import { Component, OnInit } from '@angular/core';
import {Router} from "@angular/router";
import {UserService} from "../service/user.service";
import {User} from "../model/user.model";
@Component({
selector: 'app-list-user',
templateUrl: './list-user.component.html',
styleUrls: ['./list-user.component.css']
})
export class ListUserComponent implements OnInit {
users: User[];
ngOnInit() {
this.userService.getUsers()
.subscribe( data => {
this.users = data;
});
}
addUser(): void {
this.router.navigate(['add-user']);
};
}
add-user.component.html
<div class="col-md-6">
<h2 class="text-center">Add User</h2>
<form [formGroup]="addForm" (ngSubmit)="onSubmit()">
<div class="form-group">
<label for="email">Email address:</label>
<input type="email" formControlName="email" placeholder="Email"
name="email" class="form-control" id="email">
</div>
<div class="form-group">
<label for="firstName">First Name:</label>
<input formControlName="firstName" placeholder="First Name"
name="firstName" class="form-control" id="firstName">
</div>
<div class="form-group">
<label for="lastName">Last Name:</label>
<input formControlName="lastName" placeholder="Last name" name="lastName"
class="form-control" id="lastName">
</div>
add-user.component.ts
import { Component, OnInit } from '@angular/core';
import {FormBuilder, FormGroup, Validators} from "@angular/forms";
import {UserService} from "../service/user.service";
import {first} from "rxjs/operators";
import {Router} from "@angular/router";
@Component({
selector: 'app-add-user',
templateUrl: './add-user.component.html',
styleUrls: ['./add-user.component.css']
})
export class AddUserComponent implements OnInit {
addForm: FormGroup;
ngOnInit() {
this.addForm = this.formBuilder.group({
id: [],
email: ['', Validators.required],
firstName: ['', Validators.required],
lastName: ['', Validators.required]
});
onSubmit() {
this.userService.createUser(this.addForm.value)
.subscribe( data => {
this.router.navigate(['list-user']);
});
}
edit-user.component.html
<div class="col-md-6">
<h2 class="text-center">Edit User</h2>
<form [formGroup]="editForm" (ngSubmit)="onSubmit()">
<div class="form-group">
<label for="email">Email address:</label>
<input type="email" formControlName="email" placeholder="Email"
name="email" class="form-control" id="email">
</div>
<div class="form-group">
<label for="firstName">First Name:</label>
<input formControlName="firstName" placeholder="First Name"
name="firstName" class="form-control" id="firstName">
</div>
<div class="form-group">
<label for="lastName">Last Name:</label>
<input formControlName="lastName" placeholder="Last name" name="lastName"
class="form-control" id="lastName">
</div>
edit-user.component.ts
import { Component, OnInit } from '@angular/core';
import {UserService} from "../service/user.service";
import {Router} from "@angular/router";
import {User} from "../model/user.model";
import {FormBuilder, FormGroup, Validators} from "@angular/forms";
import {first} from "rxjs/operators";
@Component({
selector: 'app-edit-user',
templateUrl: './edit-user.component.html',
styleUrls: ['./edit-user.component.css']
})
export class EditUserComponent implements OnInit {
user: User;
editForm: FormGroup;
constructor(private formBuilder: FormBuilder,private router: Router, private
userService: UserService) { }
ngOnInit() {
let userId = localStorage.getItem("editUserId");
if(!userId) {
alert("Invalid action.")
this.router.navigate(['list-user']);
return;
}
this.editForm = this.formBuilder.group({
id: [],
email: ['', Validators.required],
firstName: ['', Validators.required],
lastName: ['', Validators.required]
});
this.userService.getUserById(+userId)
.subscribe( data => {
this.editForm.setValue(data);
});
}
onSubmit() {
this.userService.updateUser(this.editForm.value)
.pipe(first())
.subscribe(
data => {
this.router.navigate(['list-user']);
},
error => {
alert(error);
});
}
}
Testing Angular 6 Application
Once our API is deployed, we can simply traverse to the client project and run the
command ng serve and hit localhost:4200
After login, you can see following screen with list of users. On this page, you can
perform actions to add, edit and delete user. Following is a sample screen for edit user.
Adding Material Design in Angular 6 App
With the release of Angular 6, we can directly run ng add @angular/material command
to add material design capabilities to an existing Angular application. By executing
below command we will be installing Angular Material and the corresponding theming
into the project.
Here, we will be only integrating material designing with Angular 6. Here is my another
article, where we have intgegrated SideNav with Angular 6 Material
ng add @angular/material
But in our existing project, we have included bootstrap 4 earlier to provide some
styling and hence let us remove it first. To so so, open index.html and remove below
scripts.
<script
src="cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="cdnjs.cloudflare.com/ajax/libs/twitter-
bootstrap/4.0.0/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="cdnjs.cloudflare.com/ajax/libs/twitter-
bootstrap/4.0.0/css/bootstrap.min.css">
Now, we will create a new module with file name material.module.ts and import all
the material design related module here and import it into our app.module.ts file.
material.module.ts
import {NgModule} from '@angular/core';
import { CommonModule } from '@angular/common';
import {
MatButtonModule, MatCardModule, MatDialogModule, MatInputModule,
MatTableModule,
MatToolbarModule
} from '@angular/material';
@NgModule({
imports: [CommonModule, MatToolbarModule, MatButtonModule, MatCardModule,
MatInputModule, MatDialogModule, MatTableModule],
exports: [CommonModule, MatToolbarModule, MatButtonModule, MatCardModule,
MatInputModule, MatDialogModule, MatTableModule],
})
export class CustomMaterialModule { }
Doing so will definitely not add any material styling to our html pages. To achieve this,
we require to re-write our html pages using material directives. Here, I am going to
change only the login.component.html for demo purpose.
login.component.html
<mat-toolbar color="primary">
<mat-toolbar-row>
<span><img src="./assets/devglan.png"></span>
<span class="example-fill-remaining-space"></span>
<span class="example-spacer"></span>
<button mat-button>About</button>
<button mat-button>Contact</button>
</mat-toolbar-row>
</mat-toolbar>
<mat-card class="example-card">
<mat-card-header>
<mat-card-title>Login</mat-card-title>
</mat-card-header>
<mat-card-content>
<form [formGroup]="loginForm" (ngSubmit)="onSubmit()">
<table class="example-full-width" cellspacing="0">
<tr>
<td>
<mat-form-field class="example-full-width">
<input matInput placeholder="Username" formControlName="email"
name="username" required>
<mat-error
*ngIf="loginForm.controls.email.errors.required">Password is required</mat-
error>
</mat-form-field>
</td>
</tr>
<tr>
<td><mat-form-field class="example-full-width">
<input matInput placeholder="Password" formControlName="password"
type="password" name="password" required>
<mat-error
*ngIf="loginForm.controls.password.errors.required">Email is required</mat-
error>
</mat-form-field></td>
</tr></table>
</form>
</mat-card-content>
<mat-card-actions>
<button mat-raised-button color="primary">Login</button>
</mat-card-actions>
</mat-card>
Now, you can compare the difference between our previous and present(material
designing) login page styling. You can download the source from github here.
Conclusion
In this article, we learned about Angular 6 and created a sample example project using
it. The source can be downloaded from github here - Angular 6 Example