0

I am using Angular 6 and I have a service that attempts to create a record in the backend database by making POST request. I implement this request in a service like so:

... usual imports and other Angular boiler plate omitted for brevity ...

export class SitesService {

  constructor(private http: HttpClient) {}

  addSite(siteName){
    const url = environment.apiUrl + '/api/v1/spi/sites/';
    const body = { 'name': siteName };

    const header = new HttpHeaders({'Content-Type':  'application/json' });
    return this.http.post(url, body, { headers: header }).pipe(map ( res => <Site>res ));
  }

I make use of the above service in my component code:

... usual imports and Angular boiler plate omitted for brevity ...

export class SitesComponent implements OnInit {

  ... local variable declaration omitted ...

  constructor(private service: SitesService) {
       ... more unrelated code omitted ...


  addSite(siteName) {
    this.showLoader = true;
    this.service.addSite(this.siteName).subscribe(
      data => this.postSuccess(data),
      error => this.postError(error)
    );
  }

  private postError(error) {
      console.log('ERROR IS');
      console.log(error);
      ... omitted ...
  }

When the API responds with a BAD REQUEST 400 I know that it provides a message along with the status number 400. As I can see it in the browsers developer's console:

enter image description here

but all my postError() method does is write to the console this:

ERROR IS
Bad Request

I would like to be able to output name: This field is required..

Here is a screen shot that shows I am getting response code 400 and not 200.

enter image description here

UPDATE

It turns out someone on my team had already implemented an interceptor. Here is its code: (I added the console.log's).

import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import {LoginService} from '../login/login.service'



@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
    constructor(private authenticationService: LoginService) {}
    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        return next.handle(request).pipe(catchError(err => {
          console.log('ErrirInterceptor err is:');
          console.log(err);
            if (err.status === 401) {
                // auto logout if 401 response returned from api
                this.authenticationService.logout();
            }
            const error = err.error.message || err.statusText;
            return throwError(error);
        }))
    }
}

When I access my troublesome api the console.log's output:

ErrirInterceptor err is:
error:
name: Array(1)
0: "This field is required."
...

But I still don't understand how to get that error message to my SitesComponent or SitesService classes.

UPDATE II

It turns out that the interceptor that was previously written didn't handle error responses generated by Django Generic Views so I updated it by changing this line ...

            const error = err.error.message || err.statusText;

... to this:

            const error = err.error.message || err.error.name || err.statusText;
7
  • Can you see the message in the header of the answer? Commented Jun 15, 2019 at 6:50
  • Yes that is what my screen shot shows. You can see my screen shot right? Commented Jun 15, 2019 at 6:51
  • You should create an interceptor and read the headers of the response. You will access the properties of the error object, such as error.status or error.message Commented Jun 15, 2019 at 6:54
  • I'd like to avoid having to do that as the documentation on the subject is not very clear how one does that. angular.io/guide/http#intercepting-requests-and-responses Commented Jun 15, 2019 at 6:56
  • can you try adding a console log inside this.postSuccess and log what's being passed ? I think it may still considering it as a success. try that and run the same endpoint and see Commented Jun 15, 2019 at 7:01

1 Answer 1

1

Create a file with the interceptor

import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpErrorResponse, HttpResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import 'rxjs/add/operator/do';


@Injectable( {
    providedIn: 'root'
} )
export class YourInterceptor implements HttpInterceptor {
    constructor () { }

    intercept ( request: HttpRequest<any>, next: HttpHandler ): Observable<HttpEvent<any>> {

        return next.handle( request )
            .do( ( response: HttpEvent<any> ) => {
                if ( response instanceof HttpResponse ) {
                    for ( const key of response.headers.keys() ) {
                        console.log(key); // ***** The message should come out here ******
                    }
                }
            }, ( error: any ) => {
                if ( error instanceof HttpErrorResponse ) {
                    console.error( error );
                    console.error( error.status );
                }
            } );
    }
}

And you import it into the main module of your application

import {
    YourInterceptor
} from './interceptors/.yourInterceptor';



    @NgModule( {
    declarations: [ . . . ],
    imports: [ . . . ],
    providers: [
        {
            provide: HTTP_INTERCEPTORS,
            useClass: YourInterceptor,
            multi: true
        }
    ],
    bootstrap: [ . . . ]
} )
Sign up to request clarification or add additional context in comments.

8 Comments

How can I make the error visible to my SitesComponent?
I think that what the api shows you is not an error object, it is a header response. with for ( const key of response.headers.keys() ) { console.log(key); } you can see all the header messages
It may be a response from the api and not an error. Do not treat it as a mistake, treat it as an response.
To show the responses of the api I created an alert service; Send whatever you want to the service and show it to them as a typical bootstrap style alert (getbootstrap.com/docs/4.3/components/alerts).
Will my SitesComponent be passed the header some how?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.