在ajax请求期间禁用按钮

时间:2017-12-04 15:38:59

标签: angular

我在jquery和Angular 1中看到了很多关于如何在处理ajax请求时禁用提交按钮的方法,但不适用于Angular 2。

到目前为止我在模板上:

<button type="submit" [disabled]="requestSent">Submit</button>

以及以下内容在Typescript中切换它的禁用状态:

requestSent: boolean = false;

this.httpService.addNewAgent(object)
            .subscribe(
            data => {

                this.requestSent = false;


            },
            error => {

                console.log(error.error);

            }
            );

但是,对于每一个组件来说,这都是漫长的过程。有没有更普遍的方法来解决这个问题?也许有拦截器?

2 个答案:

答案 0 :(得分:3)

有几种情况可以解决此问题: 第一种方法:

this.httpService.addNewAgent(object)
        .do(() => this.isLoading = true)
        .finally(() => this.isLoading = false)
        .subscribe()

第二种方法是使用主题创建服务:

 @Injectable()
 class LoadingService {
     isLoading: BehaviorSubject<boolean> = new BehaviourSubject(false);
  }

在你的意志中,你会设置这样的东西:

  this.service.isLoading(currentState);

在您的组件中:

this.service.isLoading.subscribe((state) => this.isLoading = state)

答案 1 :(得分:2)

感谢@DmitriyKhirniy的回复,但我希望在ajax请求期间有更通用的方法来禁用按钮。我找到了一种使用指令,服务和拦截器的方法。因此,使用此功能,您只需将属性disableDuringAjax应用于按钮即可。

模板:

<button type="submit" disableDuringAjax>Sign In</button>

如果您有一个也因表单验证而禁用的按钮,您可以使用:

<button type="submit" disableDuringAjax [formValid]="myForm">Sign In</button>

[formValid]只需提及表格的实例,该指令将完成剩下的工作。

指令(禁用按钮-ajax.directive.ts):

import { Component, OnDestroy, OnInit, Directive, HostListener, HostBinding, ElementRef, Input } from '@angular/core';
import { BusyService } from '../busy.service';
import { Subscription } from 'rxjs/Subscription';
import 'rxjs/add/operator/takeUntil';
import { Subject } from 'rxjs/Subject';

@Directive({
    selector: '[disableDuringAjax]'
})

export class DisableButtonDuringAjax implements OnDestroy, OnInit {

    private ngUnsubscribe: Subject<any> = new Subject();

    @Input() formValid;

    subscription: Subscription;

    constructor(private _busyService: BusyService, private el: ElementRef) {



    }




    checkFormValidation(form)
    {
        if ((form.valid == true)) {
            this.checkAjaxProgress();
        }
        if ((form.valid == false)) {
            this.el.nativeElement.disabled = true;
        }
    }


    checkAjaxProgress()
    {

        this.subscription = this._busyService.busy$
        .takeUntil(this.ngUnsubscribe).subscribe(
            response => {




                if ((response == true)) {
                    this.el.nativeElement.disabled = true;
                }

                if ((response == false)) {
                    this.el.nativeElement.disabled = false;
                }

                // Check form one more time
                if ((this.formValid != null)) {
                    if ((this.formValid.valid == false)) {
                        this.el.nativeElement.disabled = true;
                    }
                }


            }
            );
    }







    ngOnInit() {

        // If there is no form to check validation then just check the ajax progress
        if ((this.formValid == null))
        {
            this.checkAjaxProgress();
        }
        // Else check the forms validation AND ajax progress
        else
        {
            this.checkFormValidation(this.formValid);
            this.formValid.valueChanges.takeUntil(this.ngUnsubscribe).subscribe(data => this.checkFormValidation(this.formValid));
        }



    }


    ngOnDestroy() {
        this.ngUnsubscribe.next();
        this.ngUnsubscribe.complete();
    }




}

服务(busy.service.ts):

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

@Injectable()
export class BusyService {

    numberOfBusyRequests: number = 0;
    numberOfNonBusyRequests: number = 0;

    // Observable navItem source
    private _busySource = new BehaviorSubject<boolean>(null);
    // Observable navItem stream
    busy$ = this._busySource.asObservable();

    constructor() { }

    changeBusy(val) {

        if ((val == true)) {
            this.numberOfBusyRequests = this.numberOfBusyRequests + 1;
        }
        else {
            this.numberOfNonBusyRequests = this.numberOfNonBusyRequests + 1;
        }




        if (this.numberOfBusyRequests == this.numberOfNonBusyRequests) {
            this._busySource.next(false);
        }
        else {
            this._busySource.next(true);
        }




    }
}

拦截器(你自己的拦截器):

import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { Injectable } from '@angular/core';
import 'rxjs/add/operator/do';
import { BusyService } from './busy.service';

@Injectable()
export class ProgressInterceptor implements HttpInterceptor {

    constructor(private busyService: BusyService) { }

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

        return next.handle(req).do(
            event => {


                // If request was sent
                if ((event.type == 0))
                {
                    this.busyService.changeBusy("busy");
                }
                else
                {
                    this.busyService.changeBusy("not busy");
                }
            }
        )
    }
}

确保将该指令包含在app.module或共享模块中。 并确保将该服务包含在您的app.module中。