This article is a continuation to the previous one. In which we created a MEAN Stack Application with Node JS API for user registration. Here we extend the same project by adding client-side Angular 6 application with User Registration Form in MEAN Stack.
GitHub link up-to this article : https://goo.gl/EE2TuQ
MEAN Stack Tutorial Hierarchy
- CRUD Operation – Insert Update View and Delete.
- User Registration
Node JS Back End.
Angular 6 Front End (this one). - JWT User Authentication
Node JS Back End.
Create Angular 6 Application
Following angular-cli command will create a new angular 6 application with some default npm packages.
ng new Angular6
Application name is also Angular6 and our application structure will be as follows.
● src
+---● app
| +--● user
| | |--user.component.ts|.html|.css
| | +--● sign-up
| | | |--sign-up.component.ts|.html|.css
| |
| |--● shared
| | |--user.service.ts
| | |--user.model.ts
| |
| |--app.module.ts
| |--routes.ts
|
|--index.html
As per the structure, we have one parent user component and one child sign-up component. Inside shared folder we need to create service and model class files for user. For that we can use following angular-cli commands.
// user component
ng g c user
// sign-up component - from user folder
ng g c sign-up
// service class - from shared folder
ng g s user
// model class - from shared folder
ng g class user --type=model
Define User Model Class
Let’s add required properties inside User model class.
In server side Node JS API, we hade one extra property SaltSecret for encrypting user password. Here in client side we don’t need that property.
Let’s Design User Registration Form
We will design the registration form using sign-up component. For that we need a property of user model inside sign-up component typescript file. For that we will start from UserService class.
Here selectedUser property is defined inside UserService Class. Now we can inject this service class inside sign-up component, Thereby we can access the selectedUser property for designing user registration form.
Here we injected UserService Class and we have one additional emailRegex property for email validation .
Now I want to update styles.css with all required css rules for the entire application.
/* You can add global styles to this file, and also import other style files */
@import url('https://fonts.googleapis.com/css?family=Poppins');
/* BASIC */
html {
background-color: #56baed;
}
body {
font-family: "Poppins", sans-serif;
height: 100vh;
}
a {
color: #92badd;
display:inline-block;
text-decoration: none;
font-weight: 400;
}
h2 {
text-align: center;
font-size: 16px;
font-weight: 600;
text-transform: uppercase;
display:inline-block;
margin: 40px 8px 10px 8px;
color: #cccccc;
}
/* STRUCTURE */
.wrapper {
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
width: 100%;
min-height: 100%;
padding: 20px;
}
#formContent {
-webkit-border-radius: 10px 10px 10px 10px;
border-radius: 10px 10px 10px 10px;
background: #fff;
padding: 30px;
width: 90%;
max-width: 450px;
position: relative;
padding: 0px;
-webkit-box-shadow: 0 30px 60px 0 rgba(0,0,0,0.3);
box-shadow: 0 30px 60px 0 rgba(0,0,0,0.3);
text-align: center;
}
#formFooter {
background-color: #f6f6f6;
border-top: 1px solid #dce8f1;
padding: 25px;
text-align: center;
-webkit-border-radius: 0 0 10px 10px;
border-radius: 0 0 10px 10px;
}
/* TABS */
h2.inactive {
color: #cccccc;
}
h2.active {
color: #0d0d0d;
border-bottom: 2px solid #5fbae9;
}
/* FORM TYPOGRAPHY*/
input[type=button], input[type=submit], input[type=reset] {
cursor: pointer;
background-color: #56baed;
border: none;
color: white;
padding: 15px 80px;
text-align: center;
text-decoration: none;
display: inline-block;
text-transform: uppercase;
font-size: 13px;
-webkit-box-shadow: 0 10px 30px 0 rgba(95,186,233,0.4);
box-shadow: 0 10px 30px 0 rgba(95,186,233,0.4);
-webkit-border-radius: 5px 5px 5px 5px;
border-radius: 5px 5px 5px 5px;
margin: 5px 20px 40px 20px;
-webkit-transition: all 0.3s ease-in-out;
-moz-transition: all 0.3s ease-in-out;
-ms-transition: all 0.3s ease-in-out;
-o-transition: all 0.3s ease-in-out;
transition: all 0.3s ease-in-out;
}
input[type=button]:hover, input[type=submit]:hover, input[type=reset]:hover {
background-color: #39ace7;
}
input[type=button]:active, input[type=submit]:active, input[type=reset]:active {
-moz-transform: scale(0.95);
-webkit-transform: scale(0.95);
-o-transform: scale(0.95);
-ms-transform: scale(0.95);
transform: scale(0.95);
}
input[type=submit]:disabled{
background-color: #f5f6f6;
color: #7d7d7d;
}
input[type=text],input[type=password] {
background-color: #f6f6f6;
border: none;
color: #0d0d0d;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 5px;
width: 85%;
border: 2px solid #f6f6f6;
-webkit-transition: all 0.5s ease-in-out;
-moz-transition: all 0.5s ease-in-out;
-ms-transition: all 0.5s ease-in-out;
-o-transition: all 0.5s ease-in-out;
transition: all 0.5s ease-in-out;
-webkit-border-radius: 5px 5px 5px 5px;
border-radius: 5px 5px 5px 5px;
}
input[type=text]:focus,input[type=password]:focus {
background-color: #fff;
border-bottom: 2px solid #5fbae9;
}
input[type=text]:placeholder {
color: #cccccc;
}
input[type=text].invalid-textbox,input[type=password].invalid-textbox{
border-bottom: 2px solid #ed5558;
}
label.validation-message{
color:#ed5558;
}
/* ANIMATIONS */
/* Simple CSS3 Fade-in-down Animation */
.fadeInDown {
-webkit-animation-name: fadeInDown;
animation-name: fadeInDown;
-webkit-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
}
@-webkit-keyframes fadeInDown {
0% {
opacity: 0;
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
}
100% {
opacity: 1;
-webkit-transform: none;
transform: none;
}
}
@keyframes fadeInDown {
0% {
opacity: 0;
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
}
100% {
opacity: 1;
-webkit-transform: none;
transform: none;
}
}
/* Simple CSS3 Fade-in Animation */
@-webkit-keyframes fadeIn { from { opacity:0; } to { opacity:1; } }
@-moz-keyframes fadeIn { from { opacity:0; } to { opacity:1; } }
@keyframes fadeIn { from { opacity:0; } to { opacity:1; } }
.fadeIn {
opacity:0;
-webkit-animation:fadeIn ease-in 1;
-moz-animation:fadeIn ease-in 1;
animation:fadeIn ease-in 1;
-webkit-animation-fill-mode:forwards;
-moz-animation-fill-mode:forwards;
animation-fill-mode:forwards;
-webkit-animation-duration:1s;
-moz-animation-duration:1s;
animation-duration:1s;
}
.fadeIn.first {
-webkit-animation-delay: 0.4s;
-moz-animation-delay: 0.4s;
animation-delay: 0.4s;
}
.fadeIn.second {
-webkit-animation-delay: 0.6s;
-moz-animation-delay: 0.6s;
animation-delay: 0.6s;
}
.fadeIn.third {
-webkit-animation-delay: 0.8s;
-moz-animation-delay: 0.8s;
animation-delay: 0.8s;
}
.fadeIn.fourth {
-webkit-animation-delay: 1s;
-moz-animation-delay: 1s;
animation-delay: 1s;
}
/* Simple CSS3 Fade-in Animation */
.underlineHover:after {
display: block;
left: 0;
bottom: -10px;
width: 0;
height: 2px;
background-color: #56baed;
content: "";
transition: width 0.2s;
}
.underlineHover:hover {
color: #0d0d0d;
}
.underlineHover:hover:after{
width: 100%;
}
/* OTHERS */
*:focus {
outline: none;
}
#icon {
width:60%;
}
* {
box-sizing: border-box;
}
.alert {
padding: 20px;
background-color: #f44336; /* Red */
color: white;
margin-bottom: 15px;
}
.success{
padding: 20px;
background-color:#249424; /* Green */
color: white;
margin-bottom: 15px;
}
Registration form can be designed inside the sign-up.component.html as follows.
Here we have 3 input-fields for fullName, email and password with proper validations. Following validations are implemented inside the form
- FullName – Required
- Email – Required & Email Pattern
- Password – Required & Min Length
This form is designed using Template Driven Approach. So we have to add FormsModule in app.module.ts file as follows.
Call Node JS API From Angular 6
Now I will create a function inside UserService class in-order to call Node JS API From the Angular 6 Application. This function will make a POST request to Node JS API to insert new user details.
Post request is made through HttpClient object and hence we need to add HttpClientModule in app.module.ts file.
apiBaseUrl is retrieved from environment.ts file. which we have stored inside the file as follows.
Form Submit Event
Now let’s implement submit event for the form element using ngSubmit directive.
onSubmit function will be called when the form as whole is valid( ie. signUpForm.valid). Now let’s define the function inside the component.
Inside the onSubmit function we called postUser function from UserService class. So that it will insert a new user in MongoDB. resetForm function is used to reset form controls to their initial state.
Two additional properties showSucessMessage & serverErrorMessages are added to show success and error notification respectively. Inorder to show these notifications, we need to add notification div elements in component html.
Routing Configuration
Before adding routing, we need add routing-outlet in proper places. So first of all I’ll replace default text from app.component.html(default component) with routing-outlet tag. As per the application structure user component will be the parent component for sign-up component. So inside the user component we need to wrap the registration form as follows.
Now let’s add a new file for routing – routes.ts.
signup route is used for user registration form and same route will shown for default route also. Now we need to add this appRoutes constant in app.module.ts using RouterModule.
In the next article we’ll implement Node JS JWT Authentication inside this same MEAN Stack Project.