Considere una tabla dinámica, es decir, una tabla cuyas filas se construyen dinámicamente:
<table> <tbody> <tr *ngFor="let row of tableRows"> <td>{{ row.id }}</td> <td>{{ row.name }}</td> </tbody> </table> Ahora estoy agregando una nueva entrada a la variable tableRows del componente y justo después de hacerlo, emito un evento addRow . El componente, en el que uso esta tabla, maneja el evento addRow desplazando la última fila de la tabla a la vista.
El problema que tengo es que la fila de la tabla, que acabo de agregar, aún no está disponible en mi DOM en el momento en que llamo a scrollIntoView . Sin embargo, parece ser una cuestión de milisegundos, todo funciona bien al agregar el siguiente setTimeOut a mi controlador de eventos addRow :
setTimeout(() => this.scrollRowIntoView(), 0); No me gusta la idea de tener que usar un setTimeout aquí. Entonces, me pregunto, ¿hay alguna manera de esperar hasta que el DOM se haya actualizado antes de llamar a scrollIntoView() ?
Al implementar AfterViewChecked en mi componente principal, es decir, el componente que contiene la tabla y el controlador de eventos addRow, me di cuenta de lo siguiente:
El método ngAfterViewChecked() se llama DESPUÉS de onAddRow , es decir, el controlador de eventos addRow. Obviamente, quiero que sea al revés y llame a ngAfterViewChecked() ANTES de onAddRow , porque solo entonces se ha actualizado el DOM. Ahora, no puedo simplemente llamar a onAddRow dentro ngAfterViewChecked() ya que no quiero llamar a este método cada vez que se verifica la vista, sino solo si se ha emitido el evento addRow.
Me las arreglé para hacer que esto funcione introduciendo una variable booleana rowAdded a mi componente principal, que se alterna dentro ngAfterViewChecked() . Si esta variable es verdadera, llamo a scrollIntoView dentro ngAfterViewChecked() y luego alterno la variable booleana. Sin embargo, para que esto funcione, todavía necesito configurar la fila a la que quiero desplazarme dentro de mi controlador de eventos onAddRow , porque configuré una propiedad, que se marcará como "vista cambiada después de que se haya verificado" si configúralo dentro ngAfterViewChecked() .
Me parece que no se puede prever qué método se ejecuta primero ngAfterViewChecked o onAddRow , por lo que tiendo a seguir con mi solución inicial con setTimeout .