0

I have this method which is working fine in my Angular 5 application:

registerUser({ value, valid }: { value: UserRegistration, valid: boolean }) {
    this.submitted = true;
    this.isRequesting = true;
    this.errors='';
    if(valid)
    {
        this.userService.register(value.email,value.password,value.firstName,value.lastName,value.location)
                  .finally(() => this.isRequesting = false)
                  .subscribe(
                    result  => {if(result){
                        this.router.navigate(['/login'],{queryParams: {brandNew: true,email:value.email}});                         
                    }},
                    errors =>  this.errors = errors);
    }      
} 

As you can see this will call a method on userService class called register that has defined like this:

register(email: string, password: string, firstName: string, lastName: string,location: string): Observable<UserRegistration> {
    let body = JSON.stringify({ email, password, firstName, lastName,location });
    let headers = new Headers({ 'Content-Type': 'application/json' });
    let options = new RequestOptions({ headers: headers });

    return this.http.post(this.baseUrl + "/account", body, options)
      .map(res => true)
      .catch(this.handleError);
} 

Well, now I want to run the same code on my new Angular 6 application. The problem is the above code is not running there and there is some problems with map and catch method. I have read some similar answers and they suggested to use pipe method. I have tried the following, but it doesn't work as per my expectation. It successfully calls the post API on the server but it seems the this.router.navigate(['/login'] will never works. Would you please help me how can I use Angular 6 equivalent of the map method here properly?

The Angular 6 version:

registerUser({ value, valid }: { value: UserRegistration, valid: boolean }) 
{
    this.submitted = true;
    this.isRequesting = true;
    this.errors = '';
    if (valid) {
      this.userService.register(value.email, value.password, value.firstName, value.lastName, value.location, value.username)
        .pipe(
        finalize(() => this.isRequesting = false))
        .subscribe(
          result => {
            if (result) {
              this.router.navigate(['/login'], { queryParams: { brandNew: true, email: value.email } });
            }
          },
          errors => this.errors = errors);
    }

And:

 register(email: string, password: string, firstName: string, lastName: string, location: string, username: string): Observable<UserRegistration> {

    let body = JSON.stringify({ email, password, firstName, lastName, location, username });
    let headers = new HttpHeaders({ 'Content-Type': 'application/json' });

    return this.http.post<UserRegistration>(this.baseUrl + "/account", body, { headers: headers }).pipe(
      map(res =>  res ));
  }
  • what do you mean by "never works". Does it not navigate or is `navigate` never called? – Arikael Apr 10 '19 at 11:36
  • @Arikael It seems `this.router.navigate` will not executed. I even don't know how to use the `catch` part in Angular 6 to see the errors that returned. –  Apr 10 '19 at 11:37
  • 1
    It is because `RxJS`is updated to v6. So you need to update your usage of RxJS accordingly. See: https://github.com/ReactiveX/rxjs/blob/master/docs_app/content/guide/v6/migration.md – Harun Yilmaz Apr 10 '19 at 11:49

1 Answers1

0

Just like that?

return this.http.post<UserRegistration>(this.baseUrl + "/account", body, { headers: headers }).pipe(
      map(res => true));
  }

And the method's signature should be Observable<boolean> or Observable<true>. However, I don't understand why you need to return a boolean here.

Update: I would write the method

register(userRegistration: UserRegistration): Observable<{}> {
    let headers = new HttpHeaders({ 'Content-Type': 'application/json' });

    return this.http.post(this.baseUrl + "/account", userRegistration, { headers });
}

And for the caller:

      this.userService.register(value).pipe(
        finalize(() => this.isRequesting = false)
      )
      .subscribe(
         () => this.router.navigate(['/login'], { queryParams: { brandNew: true, email: value.email } }),
         (error: HttpErrorResponse) => this.errors = xxx(error) // your error handler
      );
HTN
  • 3,388
  • 1
  • 8
  • 18
  • It needs to return boolean in order to be used inside `if` part In this line `if (result) { this.router.navigate(['/login'], { queryParams: { brandNew: true, email: value.email } }); }` However your solution doesn't work. –  Apr 10 '19 at 11:40
  • Also What about the `Catch` method? Could you please add the `Catch` parts as well? –  Apr 10 '19 at 11:42
  • It seems that you don't understand how rxjs works. The `http.post` will returns an `Observable` with only one (nullable) value with everything is ok, and throws an error otherwise. So you just need to do: `http.post(...).subscribe()` without `if` If you want to catch error inside the service method, use `catchError` transformation: https://www.learnrxjs.io/operators/error_handling/catch.html , but you can do it in `subscribe` as well. – HTN Apr 10 '19 at 11:48
  • Thanks. So can you please update your answer with a working one so that I can accept your answer? –  Apr 10 '19 at 12:21
  • I have changed my method on userService to this `register(email: string, password: string, firstName: string, lastName: string, location: string, username: string) { let body = JSON.stringify({ email, password, firstName, lastName, location, username }); let headers = new HttpHeaders({ 'Content-Type': 'application/json' }); return this.http.post(this.baseUrl + "/account", body, { headers: headers }).subscribe(); }` now please let me know how should I change the caller method accordingly? –  Apr 10 '19 at 12:26
  • Thanks for the update. Would you please have a look at this question that I asked based on your updated code and let me know where is my typo? https://stackoverflow.com/questions/55627197/why-i-have-to-use-a-semi-colon-before-my-code#55627197 –  Apr 11 '19 at 07:56
  • Do you have any idea, why I have to put that extra semi-colon in order to my code works? And also why I just get an `[object Object]` as the error response? –  Apr 11 '19 at 08:43
  • As everyone said, the code is right, the problem is elsewhere. As for the [object Object], in case of error for the method `http.post` you will have an HttpErrorResponse object: https://angular.io/api/common/http/HttpErrorResponse , you should decide what to do with this object. If you treat it like a String in some function, it will call object.toString() to return `[object Object]` – HTN Apr 11 '19 at 17:26