File

src/app/register/register.component.ts

Description

Allows the user to register for a Gropius account.

Metadata

selector app-register
styleUrls ./register.component.css
templateUrl ./register.component.html

Index

Properties
Methods

Constructor

constructor(fb: FormBuilder, apollo: Apollo, router: Router, registerUserMutation: RegisterUserGQL, userAvailablyQuery: CheckUsernameGQL, notify: UserNotifyService)
Parameters :
Name Type Optional
fb FormBuilder No
apollo Apollo No
router Router No
registerUserMutation RegisterUserGQL No
userAvailablyQuery CheckUsernameGQL No
notify UserNotifyService No

Methods

backToLogin
backToLogin(e: MouseEvent)

Loads the login page.

Parameters :
Name Type Optional Description
e MouseEvent No
  • Event affecting the form reset.
Returns : void
resetForm
resetForm(e: MouseEvent)

Resets form fields and marks all controls as pristine.

Parameters :
Name Type Optional Description
e MouseEvent No
  • Event affecting the form reset.
Returns : void
submitForm
submitForm(value: literal type)

Given data needed for account creation and carries out the creation by issuing a mutation to the backend. If successfull, the user is redirected to the Login page.

Parameters :
Name Type Optional Description
value literal type No
  • Data (from the register form) that is handled.
Returns : void
validateConfirmPassword
validateConfirmPassword()

Recalculates the value and validation status of the password confirmation field. This is triggered whenever the user changes the password in the register form.

Returns : void

Properties

confirmValidator
Default value : () => {...}

Checks that the password in the Confirm Password field matches the password in the Password field.

Parameters :
Name Description
control

Password that is handled.

isLoading
Default value : false
publicClientName
Default value : environment.publicClientName
userNameAsyncValidator
Default value : () => {...}

Checks with backend to ensure that entered username is valid. A username is invalid when its taken or contains symbols like '*', etc. control is not a valid username. Emits null when username is valid

Parameters :
Name Description
control
  • Username that is handled.
validateForm
Type : FormGroup
import {Component} from '@angular/core';
import {FormBuilder, FormControl, FormGroup, ValidationErrors, Validators} from '@angular/forms';
import {Apollo} from 'apollo-angular';
import {Observable, Observer} from 'rxjs';
import {environment} from '@environments/environment';
import {CheckUsernameGQL, RegisterUserGQL, RegisterUserInput} from 'src/generated/public-graphql';
import {Router} from '@angular/router';
import {UserNotifyService} from '@app/user-notify/user-notify.service';

/**
 * Allows the user to register for a Gropius account.
 */
@Component({
  selector: 'app-register',
  templateUrl: './register.component.html',
  styleUrls: ['./register.component.css']
})
export class RegisterComponent {
  validateForm: FormGroup;
  isLoading = false;
  publicClientName = environment.publicClientName;

  constructor(
    private fb: FormBuilder,
    private apollo: Apollo,
    private router: Router,
    private registerUserMutation: RegisterUserGQL,
    private userAvailablyQuery: CheckUsernameGQL,
    private notify: UserNotifyService
  ) {
    this.registerUserMutation.client = this.publicClientName;
    this.userAvailablyQuery.client = this.publicClientName;
    this.validateForm = this.fb.group({
      username: ['', [Validators.required], [this.userNameAsyncValidator]],
      email: ['', [Validators.email, Validators.required]],
      password: ['', [Validators.required]],
      confirm: ['', [this.confirmValidator]]
    });
  }

  /**
   * Checks with backend to ensure that entered username is valid.
   * A username is invalid when its taken or contains symbols like '*', etc.
   * @param control - Username that is handled.
   * @returns Observable emitting values indicating error when string entered in
   * control is not a valid username. Emits null when username is valid
   */
  userNameAsyncValidator = (control: FormControl): Observable<any> =>
    new Observable((observer: Observer<ValidationErrors | null>) => {
      this.userAvailablyQuery.fetch({username: control.value}).subscribe(
        ({data}) => {
          // case: username already taken
          // => marks event as error
          if (!data.checkUsername) {
            // returns `{error: true}` to mark event as an error
            observer.next({error: true, duplicated: true});
          } else {
            observer.next(null);
          }
          observer.complete();
        },
        (error) => {
          this.notify.notifyError('Failed to verify user name!', error);
        }
      );
    });

  /**
   * Checks that the password in the Confirm Password field
   * matches the password in the Password field.
   * @param control Password that is handled.
   */
  confirmValidator = (control: FormControl): {[s: string]: boolean} => {
    // case: no password given
    if (!control.value) {
      return {error: true, required: true};
    }

    // case: password does not match
    else if (control.value !== this.validateForm.controls.password.value) {
      return {confirm: true, error: true};
    }
    return {};
  };

  /**
   * Recalculates the value and validation status of the password confirmation field.
   * This is triggered whenever the user changes the password in the register form.
   */
  validateConfirmPassword(): void {
    setTimeout(() => this.validateForm.controls.confirm.updateValueAndValidity());
  }

  /**
   * Given data needed for account creation
   * and carries out the creation by issuing a mutation to the backend.
   * If successfull, the user is redirected to the Login page.
   * @param value - Data (from the register form) that is handled.
   */
  submitForm(value: {username: string; email: string; password: string; confirm: string}): void {
    for (const key of Object.keys(this.validateForm.controls)) {
      this.validateForm.controls[key].markAsDirty();
      this.validateForm.controls[key].updateValueAndValidity();
    }
    const input: RegisterUserInput = {
      username: value.username,
      displayName: value.username,
      password: value.password,
      email: value.email
    };

    this.registerUserMutation.mutate({input}).subscribe(
      () => {
        this.router.navigate(['login']);
      },
      (error) => {
        this.notify.notifyError('Failed to register the user!', error);
      }
    );
  }

  /**
   * Resets form fields and marks all controls as pristine.
   * @param e - Event affecting the form reset.
   */
  resetForm(e: MouseEvent): void {
    e.preventDefault();
    this.validateForm.reset();
    for (const key of Object.keys(this.validateForm.controls)) {
      this.validateForm.controls[key].markAsPristine();
      this.validateForm.controls[key].updateValueAndValidity();
    }
  }

  /**
   * Loads the login page.
   * @param e - Event affecting the form reset.
   */
  backToLogin(e: MouseEvent): void {
    e.preventDefault();
    this.router.navigate(['login']);
  }
}
<!--Register page-->
<div class="canvas-background">
  <div class="form-container">
    <div class="logo-wrapper">
      <!-- Logo-->
      <div class="logo-container">
        <div class="logo-image">
          <img src="../../assets/Gropius.png" alt="CCIMS-Logo" height="80" />
        </div>
      </div>

      <div class="headline">
        <h2>Register</h2>
      </div>
    </div>

    <form nz-form [formGroup]="validateForm" (ngSubmit)="submitForm(validateForm.value)">
      <!-- Username form item-->
      <nz-form-item>
        <nz-form-label [nzSpan]="7" nzRequired> Username </nz-form-label>

        <nz-form-control [nzSpan]="12" nzHasFeedback nzValidatingTip="Validating..." [nzErrorTip]="userErrorTpl">
          <input nz-input formControlName="username" placeholder="" />
          <ng-template #userErrorTpl let-control>
            <ng-container *ngIf="control.hasError('required')"> Please enter a Username! </ng-container>
            <ng-container *ngIf="control.hasError('duplicated')"> This Username is taken! </ng-container>
          </ng-template>
        </nz-form-control>
      </nz-form-item>

      <!-- Email form item-->
      <nz-form-item>
        <nz-form-label [nzSpan]="7" nzRequired> Email </nz-form-label>

        <nz-form-control [nzSpan]="12" nzHasFeedback [nzErrorTip]="emailErrorTpl">
          <input nz-input formControlName="email" placeholder="" type="email" />
          <ng-template #emailErrorTpl let-control>
            <ng-container *ngIf="control.hasError('email')"> Please enter a valid Email! </ng-container>
            <ng-container *ngIf="control.hasError('required')"> Please enter your Email! </ng-container>
          </ng-template>
        </nz-form-control>
      </nz-form-item>

      <!-- Password form item-->
      <nz-form-item>
        <nz-form-label [nzSpan]="7" nzRequired> Password </nz-form-label>

        <nz-form-control [nzSpan]="12" nzHasFeedback nzErrorTip="Please enter a Password">
          <input nz-input type="password" formControlName="password" (ngModelChange)="validateConfirmPassword()" />
        </nz-form-control>
      </nz-form-item>

      <!-- Confirm Password form item-->
      <nz-form-item>
        <nz-form-label [nzSpan]="7" nzRequired> Confirm Password </nz-form-label>

        <nz-form-control [nzSpan]="12" nzHasFeedback [nzErrorTip]="passwordErrorTpl">
          <input nz-input type="password" formControlName="confirm" placeholder="" />
          <ng-template #passwordErrorTpl let-control>
            <ng-container *ngIf="control.hasError('required')"> Please enter your Password! </ng-container>
            <ng-container *ngIf="control.hasError('confirm')"> Passwords do not match! </ng-container>
          </ng-template>
        </nz-form-control>
      </nz-form-item>

      <!-- Buttons form item-->
      <nz-form-item>
        <nz-form-control [nzOffset]="7" [nzSpan]="12">
          <button nz-button nzType="primary" [disabled]="!validateForm.valid">Register</button>
          <button nz-button (click)="resetForm($event)">Reset</button>
          <button nz-button (click)="backToLogin($event)">Back</button>
        </nz-form-control>
      </nz-form-item>
    </form>
  </div>
</div>

./register.component.css

[nz-form] {
  max-width: 600px;
}

button {
  margin-left: 8px;
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""