es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Barra de progreso de Bootstrap no se actualiza automáticamente en Angular HTTP Event progress

Estoy tratando de mostrar el progreso de mi solicitud de publicación con HTTP Event usando una barra de progreso de bootstrap. El progreso del evento funciona perfectamente (lo estoy viendo en la consola), pero los cambios no se muestran en la barra de progreso A MENOS QUE haga clic en la página.
Aquí está mi servicio donde estoy usando el evento de progreso HTTP:

progress: number = 0;
uploadClubMedia(folderName, fieldName, file): Observable<any> {
    const formData: FormData = new FormData();
    formData.append('file', file);
    return new Observable((success) => {
        const req = new HttpRequest('POST', `${constants.clubApiUrl}/media-upload/mediaFiles/${folderName}/${fieldName}`, formData, {
            reportProgress: true
        });
        this.http.request(req).subscribe((event: HttpEvent<any>) => {
            switch (event.type) {
                case HttpEventType.Sent:
                    console.log('¡Se realizó la solicitud!');
                    break;
                case HttpEventType.ResponseHeader:
                    console.log('¡Se recibió el encabezado de respuesta!');
                    break;
                case HttpEventType.UploadProgress:
                    this.progress = Math.round(event.loaded / event.total * 100);
                    // this.progress$ = new BehaviorSubject<number>(this.progress);
                    console.log(`Cargado: ${this.progress}%`);
                    this.ref.tick();
                    break;
                case HttpEventType.Response:
                    console.log('¡Publicado exitosamente!', event.body);
                    success.next(event.body);
                    setTimeout(() => {
                        this.progress = 0;
                    }, 1500);
            }
        });
    });
}

Este es mi HTML:

<div class="progress form-group" *ngif="mediaService.progress > 0">
    <div class="progress-bar bg-info" role="progressbar" [style.width.%]="mediaService.progress">
        {{mediaService.progress}}%
    </div>
</div>

No puedo entender cuál es el problema. Cualquier ayuda es muy apreciada. Gracias.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    El problema parece estar relacionado con la detección de cambios. Cuando se dispara el evento de progreso, actualiza la variable de progreso en el servicio, pero el cambio no es detectado por Angular hasta que haya una interacción del usuario con la página (en este caso, hacer clic en ella).

    Para solucionar esto, puedes activar manualmente la detección de cambios inyectando ChangeDetectorRef en el servicio y llamando a su método detectChanges() después de actualizar la variable de progreso. Aquí tienes una versión actualizada del código del servicio:

    import { Injectable, ChangeDetectorRef } from '@angular/core';
    import { HttpClient, HttpEvent, HttpEventType, HttpRequest } from '@angular/common/http';
    import { Observable } from 'rxjs';
    
    @Injectable()
    export class MediaService {
      progress: number = 0;
    
      constructor(private http: HttpClient, private ref: ChangeDetectorRef) {}
    
      uploadClubMedia(folderName, fieldName, file): Observable<any> {
        const formData: FormData = new FormData();
        formData.append('file', file);
    
        return new Observable((success) => {
          const req = new HttpRequest('POST', `${constants.clubApiUrl}/media-upload/mediaFiles/${folderName}/${fieldName}`, formData, {
            reportProgress: true
          });
    
          this.http.request(req).subscribe((event: HttpEvent<any>) => {
            switch (event.type) {
              case HttpEventType.Sent:
                console.log('¡La solicitud se ha realizado correctamente!');
                break;
              case HttpEventType.ResponseHeader:
                console.log('¡Se ha recibido el encabezado de respuesta!');
                break;
              case HttpEventType.UploadProgress:
                this.progress = Math.round(event.loaded / event.total * 100);
                console.log(`Subido: ${this.progress}%`);
                this.ref.detectChanges(); // activar manualmente la detección de cambios
                break;
              case HttpEventType.Response:
                console.log('¡Se ha publicado correctamente!', event.body);
                success.next(event.body);
                setTimeout(() => {
                  this.progress = 0;
                  this.ref.detectChanges(); // activar manualmente la detección de cambios
                }, 1500);
            }
          })
        })
      }
    }
    

    Con este cambio, la barra de progreso debería actualizarse sin requerir ninguna interacción del usuario.

Comments are closed.