我在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);
}
);
但是,对于每一个组件来说,这都是漫长的过程。有没有更普遍的方法来解决这个问题?也许有拦截器?
答案 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中。