Separating Login and Register forms into different components is useful, because we can reuse them in other pages if needed (for example dedicated login and register pages without a dialog)
Let’s start by generating our first component, Home, with Angular CLI:
$ ng g c home
g = generate and c = component
This will create ./src/app/home folder with home component class, its template and stylesheet, Angular CLI will also add it to Main App Module’s declarations array automatically.
Now we need to create a route for it, open ./src/app/app-routing.module.ts
Import the HomeComponent:
import {HomeComponent} from "./home/home.component";
and add home route to routes array:
const routes: Routes = [{path: '',children: []},{path: 'home',component: HomeComponent}];
We’ll also make it the default route:
const routes: Routes = [{path: '',component: HomeComponent,pathMatch: 'full'},{path: 'home',component: HomeComponent}];
Now if we go to http://localhost:4200 HomeComponent will be displayed by default
Same procedure for Toolbar Component:
$ ng g c toolbar
Setup toolbar’s html template:
For now we’ll display all actions, we’ll implement the conditional state later.
Change ./src/app/home/home.component.html to something more appealing:
Edit ./src/app/app.component.html as follows to display our toolbar and wrap the router outlet in container class:
And here’s what we get so far:
Now we need to create the AuthDialogComponent which will display Login/Register forms:
$ ng g c auth-dialog
Let’s edit the AuthDialogComponent file in ./src/app/auth-dialog/auth-dialog.component.ts
Auth Dialog Component will have an Input decorator (line 11) authMode, it takes 2 possible values, ‘login’ or ‘register’, this will allow us to pick the initial form to display when the dialog shows up (login or register form). The default value of this input is ‘login’.
modalActions (line 12) is an event emitter, required by Materialize Dialog Directive, we’ll emit events on it to open or close our dialog.
openDialog (line 18) method takes a mode as its parameter, will set the current auth mode and display the dialog, if no parameter is passed, login will be the default.
isLoginMode and isRegisterMode methods will help us to display the login or register forms conditionally.
Edit this dialog’s template, ./src/app/auth-dialog/auth-dialog.component.html:
On line 2, we are using materialize modal directive, and passing modalActions event emitter for its materializeActions input to be able to control the dialog by emitting events on it.
For now all this dialog is displaying is its current mode on line 17, and the ability to switch modes on lines 23 and 26. The *ngIf structural directive takes a boolean expression, if the expression is true, it will display the node, or hide it otherwise (remove it from the DOM).
Let’s display this dialog when we click on register or login actions in the toolbar.
In ./src/app/toolbar/toolbar.component.html include the auth-dialog component, and create click events on Login and Register actions to open the Auth Dialog:
#authDialog (line 24) is a reference to the AuthDialogComponent of our ToolbarComponent view, it will allow us to access the AuthDialogComponent class from the ToolbarComponent class.
./src/app/toolbar/toolbar.component.ts:
import {Component, OnInit, ViewChild} from '@angular/core';import {AuthDialogComponent} from "../auth-dialog/auth-dialog.component";
@Component({selector: 'app-toolbar',templateUrl: './toolbar.component.html',styleUrls: ['./toolbar.component.sass']})export class ToolbarComponent implements OnInit {
@ViewChild('authDialog') authDialog: AuthDialogComponent;
constructor() { }
ngOnInit() {}
presentAuthDialog(mode?: 'login'| 'register'){this.authDialog.openDialog(mode);}
}
ViewChild decorator will reference the AuthDialogComponent from our template so we can access its methods and attributes directly from our ToolbarComponent class.
presentAuthDialog method takes an optional mode parameter (notice the question mark), AuthDialogComponenet’s openDialog method defaults the mode to ‘login’, so if we want to open the login dialog, we can just call presentAuthDialog() without any params.
So this is what we get for the Auth Dialog so far:
We’ll use the Token Service to display the correct actions in the toolbar depending on wether or not the user is authenticated, for that, we can use the userSignedIn() method which returns true of the user is logged in.
Import and inject Angular2TokenService into our ToolbarComponent:
Now we can use it on our toolbar template to hide/show actions conditionally, we’ll also attach the signOut method to its action:
We’re almost finished. Let’s generate login and register form components.
$ ng g c login-form
$ ng g c register-form
We have two text inputs (email & password) both of which are required for form to have a valid state. We are using Angular’s two way data binding on line 12 and 24 to bind the input values to signInUser object in our component class, which means the values will be updated when they are modified in the HTML form by the user, and also updated in the view if they are modified programatically in the component class.
Submit button (line 31) will be in disabled state unless the form becomes valid (line 32).
Login form will have an output onFormResult (line 16), which is an event fired when login request completes, so the parent components can listen and act on it.
We’ll inject the Token Service into our component (line 17) and use its signIn method when the form is submitted. When the login action completes, we’ll emit an event on onFormResult output, with a payload containing the result (lines 31 and 37), this will notify the parent components.
Pretty similar to login from, but have have an additional password confirmation text field and its validation.
Similar to login form, register form has an Output event emitter, onFormResult, that fires when register request completes.
In the auth dialog component class, create the event handlers for onFormResult events emitted by login and register form components, if the the login/register was successful, close the dialog, otherwise display the error returned by our RoR server in an alert window:
Notice the toolbar actions updating their state automatically when user logs in and out.
Final source code for this part is available on Github: https://github.com/avatsaev/angular-token-auth-seed/tree/final