2

I am trying to create a spinner when button is clicked but it seems its not being run, this is what i did in my component.html

<button type="submit" class="btn  btn-accent btn-block btn-flat b-r-10" style="background: #FF473A;">
  Sign In
  <i class="fa fa-spinner fa-spin" *ngIf="loading"></i>
</button>

and in component.ts

export class LoginComponent implements onInit {
  private loading: boolean;

  //form ngSubmit function()
  login() {
    if (this.user.email, this.user.password) {
      this.loading = true;
      this.userSrv.login(this.user.email, this.user.password); //api call here
      this.loading = false;
    }
  }
}

okay my service.ts

import { Injectable } from '@angular/core';
import { Http, Headers, RequestOptions } from '@angular/http';
import { Router } from '@angular/router';
import { Globals } from '../shared/api';
import 'rxjs/add/operator/toPromise';
import { Observable } from 'rxjs/Observable';

@Injectable() export class UserService {

private loginUrl = this.globals.LOGIN_URL;
private loggedIn = false;
public loading: boolean = false;


constructor(private http: Http, private router: Router, private globals: Globals) { }

login(email: string, password: string) {
    let headers = new Headers();
    this.loading = true;
    headers.append('Content-Type', 'application/json');
    return this.http.post(this.loginUrl, JSON.stringify({ email, password }), { headers })
        .subscribe(res => {
            let data = res.json();

            if (data.token) {
                this.loading = false;
                window.location.href = '/';
            }
            else {
                this.loading = false;
                this.router.navigateByUrl('/login');
            }

        }, error => {
            this.loading = false;
        })
};

and this is what i hope to achieve when clicked

enter image description here

CE0
  • 191
  • 3
  • 7
  • 18
  • @Vikas thanks for downvoting, let me update the question to display all what i have – CE0 May 12 '18 at 08:11

3 Answers3

5

HttpModule is deprecated you must use the new HttpClientModule whcih by default formats the response to JSON so we no longer need to parse it using response.json():

Revised service code: Return Observable from your service and subscribe it in your component

    import { Injectable } from '@angular/core';
    import { HttpHeaders,HttpClient } from '@angular/common/http';
    import { Router } from '@angular/router';
    import { Globals } from '../shared/api';

    import { Observable } from 'rxjs/Observable';
    private loginUrl = this.globals.LOGIN_URL;
    private loggedIn = false;
    public loading: boolean = false;


    constructor(private http: HttpClient, private globals: Globals) { }

    login(email: string, password: string):Observable<any> {
       const headers = new HttpHeaders({'Content-Type':'application/json;})

    return this.http.post(this.loginUrl, JSON.stringify({ email, password }), { headers });
}

Revised Component:
Put the logic inside susbscribe call back to ensure that spinner goes off only when your request is resolved.

   export class LoginComponent implements onInit {
      constructor(private router:Router){}
      public loading: boolean;

      //form ngSubmit function()
      login() {
        if (this.user.email, this.user.password) {
          this.loading = true;
          this.userSrv.login(this.user.email, this.user.password).subscribe(res 
                => {
            let data = res;

            if (data.token) {
                this.loading = false;
                window.location.href = '/';
            }
            else {
                this.loading = false;
                this.router.navigateByUrl('/login');
            }

        }, error => {
            this.loading = false;
        });
}}

revised HTML

<button type="submit" class="btn  btn-accent btn-block btn-flat b-r-10" (click)="login()" style="background: #FF473A;">
      Sign In
      <i class="fa fa-spinner fa-spin" *ngIf="loading"></i>
    </button>
Vikas
  • 11,859
  • 7
  • 45
  • 69
  • Thanks converting to HttpClientModule did it but now I have to change it for everywhere else I used HttpModule....nice one – CE0 May 12 '18 at 13:50
  • Glad I could help – Vikas May 12 '18 at 14:03
  • Can we have a private? Have an error resulting from the change that i need help on...thanks bro...I don't know how to initiate chat though so if you can I will appreciate. – CE0 May 12 '18 at 14:11
  • you could update your question with the new error you getting – Vikas May 12 '18 at 14:20
  • i will just make it a new question as they are unrelated really and i will past the link to the question here for you...okay? – CE0 May 12 '18 at 14:23
  • okay nice so here is the link https://stackoverflow.com/questions/50307636/angular-5-pass-headers-properly-in-http-get-requests – CE0 May 12 '18 at 15:06
  • Beautiful and simple solution – USQ91 Nov 21 '19 at 01:08
2

First in your component.html

<button type="submit" class="btn  btn-accent btn-block btn-flat b-r-10" (click)="login()" style="background: #FF473A;">
      Sign In
      <i class="fa fa-spinner fa-spin" *ngIf="loading"></i>
    </button>

And now you could put this.loading=false; in subscriber like this:

export class LoginComponent implements onInit {
private loading: boolean;

 //form ngSubmit function()
 login() {
  if (this.user.email, this.user.password) {
      this.loading = true;
      this.userSrv.login(this.user.email, this.user.password)
      .subscribe((res: any) =>  {
               this.loader = false;
               //check your condition here and redirect to 
          },
           (error) => {
              this.loader = false;
        });
        }
     }
  }

In your service.ts file like:

login(email: string, password: string) {
    return this.http.post(this.loginUrl, JSON.stringify({
       email, password
    }));
};

Hope this will help you !

Sanoj_V
  • 2,936
  • 1
  • 12
  • 28
  • using your code in service.ts still didn't work as expected login(email: string, password: string) { this.loading = true; return this.http.post(this.loginUrl, JSON.stringify({ email, password })) .subscribe(res => { this.loading = false; window.location.href = '/'; } else { this.loading = false; this.router.navigateByUrl('/login'); } }, error => { this.loading = false; }) }; @Sanoj_V – CE0 May 12 '18 at 06:52
  • sorry for the wrong formatting, couldn't figure out how to format in comments – CE0 May 12 '18 at 07:02
  • Use this in your service.ts `login(email: string, password: string) { return this.http.post(this.loginUrl, JSON.stringify({ email, password })); };` only. – Sanoj_V May 12 '18 at 07:10
  • error: property "subscribe" does not exist on type "void". the error comes up on the subscribe part. you should know that i'm using old Http and not HttpClient. think it matters here? – CE0 May 12 '18 at 07:27
  • use observable in service.ts=> login function `login(email: string, password: string): Observable{ return this.http.post(this.loginUrl, JSON.stringify({ email, password })); }` Observable need to import in service.ts – Sanoj_V May 12 '18 at 07:31
  • import { Observable } from 'rxjs/Observable'; – Sanoj_V May 12 '18 at 07:55
0

ng-if did not work for me for whatever reason. Another solution is:

  1. Use button-spinner instead of input for spinning buttons
  2. Tag the spinning button by the id <button-spinner id="btn1">
  3. In the callbacks in the controller, use broadcast and id of the button $scope.$broadcast('btnSpinnerSuccess', 'btn1');

step 3 goes in the method that is called on click of btn1

Niraj Motiani
  • 71
  • 1
  • 8