Tengo un componente de botón genérico:
@Component({ selector: "debounced-submit-button" template: ` <button (click)="debounceClick.emit()" [disabled]="disabled"> <ng-content></ng-content> </button> `}) export class DebouncedSubmitButton { @Input() disabled: boolean = false; @Output() debounceClick = new EventEmitter(); }Y lo uso como:
@Component({ selector: "example-component", template: ` <debounced-submit-button (debounceClick)="makeBackendCall()" disabled="loading"> </debouncedSubmitButton> `}) export class ExampleComponent { loading = false; makeBackendCall(): Promise<any> { this.loading = true; return apiService.makeCall() .then(result => useResult(result)) .finally(() => this.loading = false); } }Por lo tanto, no puede volver a hacer clic en el botón mientras la llamada HTTP está en curso. Sin embargo, esto requiere que incluya muchas llamadas repetitivas para rastrear la "carga" donde sea que tenga un botón.
¿Hay alguna forma de comunicar los resultados del (debounce-click) al debounced-submit-button , para que pueda ubicar centralmente mi código de desactivación? Como, idealmente, solo quiero
<debounced-submit-button (debounce-click)="makeBackendCall()">y hacer que el componente sea algo como
@Component({ selector: "debounced-submit-button" template: ` <button (click)="onClick($event)" [disabled]="disabled"> <ng-content></ng-content> </button> `}) export class DebouncedSubmitButton { disabled: boolean = false; @Output() debounceClick = new EventEmitter(); onClick() { this.disabled = true; // I don't think this works, but I want the return value of the callback function httpCall = debounceClick.emit(); httpCall.finally(() => this.disabled = false); } } Como, obviamente, esto no funciona, porque el emisor de eventos debounceClick podría estar suscrito por múltiples oyentes, o por ningún oyente. Solo estoy buscando una forma menos repetitiva de comunicarme con DebouncedSubmitButton que la llamada a la API se realizó y que el usuario debería poder interactuar con ella nuevamente. ¿Hay alguna forma de hacer esto?
cree una bandera en el servicio api, dentro del servicio, ¡fundamentalmente habrá cuatro implementaciones en su mayoría! ( GET, POST, PUT, DELETE ), por lo que solo necesitamos alternar la bandera, usamos el operador de toque, que se ejecutará después de que ocurra la llamada a la API, pero no hará nada con la respuesta. luego use esa bandera para habilitar/deshabilitar botones en cualquier componente. ¡Por favor revise la implementación a continuación!
import { Injectable } from '@angular/core'; import { tap } from 'rxjs/operators'; @Injectable() export class ApiService { apiCallInProgress = false; constructor(private http: HttpClient) { } get(): Observable<any> { this.apiCallInProgress = true; return this.http.get('https://jsonplaceholder.typicode.com/users').pipe( tap(() => {this.apiCallInProgress = false;} ); } }Utilice la variable de servicio en el componente.
@Component({ selector: "debounced-submit-button" template: ` <button (click)="debounceClick.emit()" [disabled]="getDisabled()"> <ng-content></ng-content> </button> `}) export class DebouncedSubmitButton { @Output() debounceClick = new EventEmitter(); constructor(apiService: ApiService){} getDisabled() { return this.apiService.apiCallInProgress; }}