Grim
Grim

Reputation: 2097

Angular 4 on submit display error based on response from server

I have spent several hours trying to show an error when a form submits and returns an error status code. I can't seem to figure this out...

Login form component in the comments below i showed where id like to tell the form that it is invalid or valid.

import { Component, OnInit, Input, Output, EventEmitter  } from '@angular/core';
import { Router } from '@angular/router';
import { FormBuilder, FormGroup, Validators, NgForm } from "@angular/forms";
import { AuthenticationService } from "../../../services/authentication.service";
import { User } from "../../../domain/user";


@Component({
  selector: 'login-form',
  templateUrl: './login-form.component.html'
})
export class LoginFormComponent implements OnInit {

  loginForm: FormGroup;
  post: any;
  username: string;
  password: string;
  user: User;
  errorMessage: string  = '';


  constructor(private fb: FormBuilder, private router: Router, private authenticationService: AuthenticationService) {
    this.loginForm = fb.group({
      'username': [null, Validators.required],
      'password': [null, Validators.required],
      'login': false
    });
  }


  ngOnInit() {
    this.authenticationService.logout(); // reset login status
  }


  login(values) {
    this.username = values.username;
    this.password = values.password;

    this.authenticationService.login(this.username, this.password)
      .subscribe(result => {
          if (result === true) {
            this.router.navigate(['/']);
            localStorage.setItem('currentUser', JSON.stringify(this.user));
            // here form should be valid
          } else {
            this.errorMessage = 'Username or password is incorrect';
            // here form should be invalid
          }
      });
  }
}

Login Form Html, the second <div> is the error id like shown after the form submits.

<form id="loginForm" [formGroup]="loginForm" (ngSubmit)="login(loginForm.value)" novalidate>
  <div class='form-text error' *ngIf="submitted">
    <div *ngIf="loginForm.invalid" class="help-block error small">Username or password is incorrect.</div>
  </div>
  <div class="form-group">
    <label class="control-label" for="username">Username</label>
    <input type="text" placeholder="Please enter your usename" title="Please enter you username" required value=""
           id="username" class="form-control" name="username" formControlName="username">
    <div class='form-text error' *ngIf="loginForm.controls.username.touched">
      <div *ngIf="loginForm.controls.username.hasError('required')" class="help-block error small">Username is required.</div>
    </div>
    <span *ngIf="loginForm.controls.username.valid || !loginForm.controls.username.touched"  class="help-block small">Your unique username</span>
  </div>
  <div class="form-group">
    <label class="control-label" for="password">Password</label>
    <input type="password" title="Please enter your password" placeholder="******" required value=""
           id="password" class="form-control" name="password" formControlName="password">
    <div class='form-text error' *ngIf="loginForm.controls.password.touched">
      <div *ngIf="loginForm.controls.password.hasError('required')" class="help-block error small">Password is required.</div>
    </div>
    <span *ngIf="loginForm.controls.password.valid || !loginForm.controls.password.touched" class="help-block small">Your strong password</span>
  </div>
  <div>
    <button type="submit" class="btn btn-accent" [disabled]="!loginForm.valid">Login</button>
    <a class="btn btn-default" routerLink="/register">Register</a>
  </div>
</form>

Upvotes: 2

Views: 6472

Answers (2)

Grim
Grim

Reputation: 2097

So within my authentication service class I wasn't handling the errors properly. I changed my login method within the authentication service to include a catch.

  login(username: string, password: string): Observable<boolean> {
    let user = JSON.stringify({ username: username, password: password });
    let headers = new Headers({ 'Content-Type': 'application/json' });
    let options = new RequestOptions({ headers: headers });

    return this.http.post(this.loginUrl, user, options)
      .map(function(res){
        let data = res.json();
        alert(res.status);

        if (data) {
          this.token = data.token;
          localStorage.setItem('currentUser', JSON.stringify({ username: username, token: this.token }));
          return true; // successful login
        } else {
          return false; // failed login
        }
      })
      .catch((error:any) => Observable.throw(error.json().error || 'Server error'));
  }

Then within my login form component I changed the use of the auth service login method to:

  login(values) {
    this.username = values.username;
    this.password = values.password;

    this.authenticationService.login(this.username, this.password)
      .subscribe(result => {
          if (result === true) {
            this.router.navigate(['/']);
            localStorage.setItem('currentUser', JSON.stringify(this.user));
          }
      },
      err => {
        this.authenticationFlag = false;
      });
  }

as @Wasif Khan put in his answer all I needed was a component variable. This was too long for a comment.

Upvotes: 1

Wasif Khan
Wasif Khan

Reputation: 954

It is error from server side, your form is valid here. So, set flag to false in your failure handler.

Component:

Make a variable for it first:

export class LoginFormComponent implements OnInit {

  loginForm: FormGroup;
  post: any;
  username: string;
  password: string;
  user: User;
  errorMessage: string  = '';
  authenticationFlag: boolean = true;

and in your login method:

login(values) {
    this.username = values.username;
    this.password = values.password;

    this.authenticationService.login(this.username, this.password)
      .subscribe(result => {
          if (result === true) {
            this.router.navigate(['/']);
            localStorage.setItem('currentUser', JSON.stringify(this.user));
            // here form should be valid
          } else {
             this.authenticationFlag = false;
          }
      });
  }

HTML Template:

Change this code:

<div class='form-text error' *ngIf="submitted">
    <div *ngIf="loginForm.invalid" class="help-block error small">Username or password is incorrect.</div>
</div>

By this:

<div *ngIf="!authenticationFlag" class="help-block error small">Username or password is incorrect.</div>

Upvotes: 4

Related Questions