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.

Angular: La variable no se actualiza en la vista dentro de dos bucles anidados.

Estoy intentando actualizar el valor de progreso en una operación de ’round-robin’, pero el valor % no se actualiza en la vista, pero sí en console.log().

He intentado utilizando ngZone y el método DetectorChanges, pero ninguno funcionó.

Aquí te dejo el código. Gracias de antemano.

   this.pageInfo.listPdfs.forEach((item,x) =>{
    this.pageInfo.listPdfs.forEach((item2,y) =>{
      if(x != y){
        let diff = jsdiff.diffWords(this.pageInfo.listPdfs[x].merged, this.pageInfo.listPdfs[y].merged)
        let removeds = diff.filter(el => el.removed == true).map(item => item.value).join(' ');
        let shared = diff.filter(el => el.removed === undefined && el.added === undefined).map(item => item.value).join(' ');
        let percent = (shared.trim().split(' ').filter(el => el != '').length / (removeds.trim().split(' ').filter(el => el != '').length + shared.trim().split(' ').filter(el => el != '').length)) * 100;
        this.pageInfo.resultsPdf.push({
          origin      : this.pageInfo.listPdfs[x], 
          destination : this.pageInfo.listPdfs[y],
          diff        : diff,
          percent     : percent
        })
        count++;
        this.ngZone.run(()=>{
          this.pageInfo.progressAnalyzer = (count / totalRevitions)*100; // <-- ESTO NO SE ACTUALIZA EN LA PLANTILLA
          console.log(this.pageInfo.progressAnalyzer); // <-- ESTO FUNCIONA 
          this.changeDetectorRef.detectChanges();
        });
        console.log(this.pageInfo.progressAnalyzer + '%');
      }
    })
  })

Y en mi vista, simplemente es {{pageInfo.progressAnalyzer}} pero nunca se actualiza.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    El problema probablemente se debe a la forma en que se activa el mecanismo de detección de cambios en Angular. Dado que el valor de progreso se actualiza dentro de bucles anidados, es posible que Angular no esté detectando los cambios ya que se producen fuera del ámbito del componente.

    Una forma de solucionar este problema es utilizar el servicio ChangeDetectorRef para activar manualmente la detección de cambios después de actualizar el valor de progreso. Sin embargo, en el código proporcionado, parece que este enfoque no funcionó.

    Otra opción es utilizar la biblioteca RxJS para crear una secuencia observable que emita el valor de progreso en cada iteración del bucle. Esto permitirá que Angular realice un seguimiento adecuado de los cambios y actualice la vista en consecuencia.

    Aquí tienes un ejemplo de cómo se puede hacer esto:

    1. Importa los operadores RxJS necesarios:
    import { from } from 'rxjs';
    import { tap } from 'rxjs/operators';
    
    1. Modifica el bucle para emitir el valor de progreso como un observable:
    from(this.pageInfo.listPdfs).pipe(
      mergeMap((item, x) =>
        from(this.pageInfo.listPdfs).pipe(
          filter((item2, y) => x !== y),
          map(item2 => {
            const diff = jsdiff.diffWords(item.merged, item2.merged);
            const removeds = diff.filter(el => el.removed).map(item => item.value).join(' ');
            const shared = diff.filter(el => el.removed === undefined && el.added === undefined).map(item => item.value).join(' ');
            const percent =
              ((shared.trim().split(' ').filter(el => el !== '').length /
                (removeds.trim().split(' ').filter(el => el !== '').length +
                  shared.trim().split(' ').filter(el => el !== '').length)) *
                100
              ).toFixed(2);
    
            return {
              origin: item,
              destination: item2,
              diff: diff,
              percent: percent,
            };
          }),
          tap(() => {
            count++;
            const progressAnalyzer = (count / totalRevitions) * 100;
            console.log(progressAnalyzer);
            this.pageInfo.progressAnalyzer = progressAnalyzer;
          })
        )
      )
    ).subscribe(result => this.pageInfo.resultsPdf.push(result));
    
    1. Modifica la vista para mostrar el valor de progreso:
    {{ pageInfo.progressAnalyzer | number: '1.0-2' }}%
    

    En este ejemplo, el operador from se utiliza para crear una secuencia observable a partir del array listPdfs. El operador mergeMap se utiliza para crear un observable anidado que itera sobre el array nuevamente para comparar cada elemento con todos los demás.

    Dentro del observable anidado, el valor de progreso se calcula como antes, pero ahora se emite como parte de la secuencia observable utilizando el operador tap. Esto permite que Angular detecte los cambios y actualice la vista correctamente.

    Finalmente, se utiliza el método subscribe para agregar cada resultado al array resultsPdf.

Comments are closed.