1

In my Angular 12 application, I have this custom error message from the API JSON response from the backend, which displays on POSTMAN whenever there is error:

trait ApiResponse
{
    public function coreResponse($message, $data = [], $statusCode, $isSuccess = true)
    {
        // Check the params
        if(!$message) return response()->json(['message' => 'Message is required'], 500);

        // Send the response
        if($isSuccess) {
            return response()->json([
                'message' => $message,
                'error' => false,
                'code' => $statusCode,
                'results' => $data
            ], $statusCode);
        } else {
            return response()->json([
                'message' => $message,
                'error' => true,
                'code' => $statusCode,
            ], $statusCode);
        }
    }

    public function success($message, $data, $statusCode = 200)
    {
        return $this->coreResponse($message, $data, $statusCode);
    }

    public function error($message, $data, $statusCode = 500)
    {
        return $this->coreResponse($message, null, $statusCode, false);
    }

}

Controller:

use ApiResponse;

public function login(LoginRequest $request)
{
try {
    $confirmUser = User::where('active', 1)->where(function ($query) use($request) {
        $query->where('email', $request->username)->orWhere('mobile_number', $request->username);
    })->whereNull('deleted_at')->first();
    if(!$confirmUser){
        return $this->error('User doesn\'t exist', 404);
    }
    $authenticated = false;
    $remember = $request->remember_me ? true : false;
    if (Auth::attempt(['email' => $request->username, 'password' => $request->password], $remember)) {
        $authenticated = true;
    } elseif (Auth::attempt(['mobile_number' => $request->username, 'password' => $request->password], $remember)) {
        $authenticated = true;
    }
    if ($authenticated == true) {
        $user = Auth::user();
        $tokenResult = $user->createToken('School');
        // User Log
        if(Auth::loginUsingId($user->id))
        {
            $user->update([
                 'last_login_at' => now(),
            ]);
        }
        $res = User::with(['roles'])->find($user->id);
        return $this->success('You have successfully Logged In.', [
            'user'          => $res,
            'access_token'  => $tokenResult->accessToken,
            'token_type' => 'Bearer',
            'expires_at' => Carbon::parse(
                $tokenResult->token->expires_at
            )->toDateTimeString()
        ]);
    } else {
        return $this->error('Invalid User Credential', 401);
    }
    } catch(\Exception $e) {
        Log::error($e);
        return $this->error($e->getMessage(), $e->getCode());
    }
}

failure:

{
    "message": "Authntication fails",
    "error": true,
    "code": 500
}

or

{
  "success": false,
  "message": "Email is Required!",
  "data": []
 }

if this is applied:

return $this->error($e->getMessage(), $e->getCode());

Note: for error data doesn't matter

success:

{
  "message": "You have successfully Logged In.",
  "error": false,
  "code": 200,
  "results": {
      "user": {
          "id": 1,
          "email": "[email protected]",
          "mobile_number": "+01977885544",
          "roles": [
            {
                "id": 1,
                "name": "Teacher",
                "guard_name": "api",
                "created_at": "2021-05-24T07:02:13.000000Z",
                "updated_at": "2021-05-24T07:02:13.000000Z",
                "pivot": {
                    "model_id": 1,
                    "role_id": 1,
                    "model_type": "App\\Models\\User"
                }
            }
         ]
       },
      ],

     "access_token": "something",
     "token_type": "Bearer",
     "expires_at": "2021-07-06 14:26:17"
  }
}

Then in my Angular component I have this:

return this.api.post('auth/user/login', data, headers)
  .pipe(first())
  .subscribe(
    data => {
      this.dataHandler(data);
    },
      err => {
      this.toastr.error(err.message);
    });
 }


dataHandler(data: any){
  this.auth.changeAuthStatus(true);
  this.router.navigateByUrl('/welcome');
  Swal.fire({
  position: 'center',
  icon: 'success',
  title: data.message,
  showConfirmButton: false,
  timer: 10000
 });
}

Whenever there is Successful login, it works. It displays the successful message as in:

title: data.message

That is:

"message": "You have successfully Logged In",

But when there is failure, it's not displaying:

"message": "Authentication fails",

as in:

  err => {
  this.toastr.error(err.message);

But displays Internal Server Error

Then when I changed:

this.toastr.error(err.message)

to

this.toastr.error(err.error.message)

I got this:

ERROR TypeError: Cannot read property 'message' of undefined

How do I make it to display the Custom Error Message:

{
    "message": "User doesn't exist",
    "error": true,
    "code": 500
}
4
  • What you have as a HTTP status code from the backend? I guess in both cases you send 200 OK. and add the error only in the payload with "code": 4500 Commented Jun 29, 2021 at 13:07
  • @robert - Sorry I don't understand what you mean. And how do I achieve this? Kindly give a sample. Commented Jun 29, 2021 at 13:09
  • Sounds like err is not what you think it is. Your server should not be returning an HTTP Status of 500 if authentication fails; it should be returning 401 or something in that range. Regardless, it's up to your api service to parse data returned as needed. Commented Jun 29, 2021 at 13:18
  • 1
    I meant what @Brian Smith wrote in his answer, check the HTTP status code in both cases. If you return 200 then error callback will never executed. Commented Jun 29, 2021 at 13:51

1 Answer 1

2

With your set up, your API will return a success (200) response even on Error. You handling the error and passing it back with your generic class (message, error, code).

return this.api.post('auth/user/login', data, headers)
  .pipe(first())
  .subscribe(
    data => {
      // Since you are handling the error in the API, it seems as your result will continue here with the error. 
      if (!data.error) {
        this.dataHandler(data);    
      }
      else {
        this.toastr.error(data.message);
      }
    },
      err => {
      this.toastr.error(err.message);
    });
 }
Sign up to request clarification or add additional context in comments.

2 Comments

I got two errors now: I highlights: if (!data.error): with the message - Property 'error' does not exist on type 'Object'.ts. And also, this.toastr.error(data.message); with the message: Property 'message' does not exist on type 'Object'
Please update your question with what object is expected from 'data' what is your API returning? Can you provide the class and even the API controller?

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.