Cómo saber si una página se está cargando en un componente de tema / widget?

Siento que probablemente me esté perdiendo algo obvio aquí, pero no logro descifrarlo. Tengo un componente de tema que carga algunos widgets y estoy utilizando el siguiente código para volver a renderizarlos después de que el usuario navega a una nueva página (tomado de los banners de categoría):

api.decorateWidget("my-widget:after", (helper) => {
    helper.widget.appEvents.on("page:changed", () => {
      helper.widget.scheduleRerender();
    })
});

Sin embargo, este código espera hasta que la nueva página se ha cargado para actualizar el widget. Lo que espero hacer es ocultar el contenido de mi widget tan pronto como alguien haga clic en un enlace a otra página, de manera similar a cómo la funcionalidad nativa de Discourse oculta elementos y muestra un spinner de carga inmediatamente al hacer clic.

Veo en app/assets/javascripts/discourse/app/templates/discovery.hbs que el contenedor div observa una variable “loading”, pero no logro averiguar de dónde proviene ni cómo “conectarme” a ella u observar el estado de carga en mi widget.

Agradecería cualquier respuesta o simplemente que me indicaran la dirección general correcta. :slight_smile:

Gracias,

Zach

1 me gusta

Pensé que sería bueno volver a subir esto; estoy dispuesto a pagar por soporte premium para obtener una respuesta si es necesario.

¿Podrías describir brevemente qué comportamiento se desea y en qué páginas exactas?

Puedes probar queueRerender() en lugar de scheduleRerender().

Gracias por las respuestas, chicos.

Tengo varios widgets que he creado para ciertas páginas de categorías y, idealmente, me gustaría ocultarlos inmediatamente cuando alguien navegue fuera de una página. Aquí hay una demostración en video de Loom de 45 segundos de lo que busco: Google Chrome - Latest Rental Cities/California topics - Afford Anything Forums - Google Chrome | Loom

@hawm No estoy seguro de que la re-renderización en cola sea lo que necesito aquí, ya que esto no se trata realmente de volver a renderizar mis widgets, sino de darles a mis widgets la capacidad de detectar si la aplicación global de Discourse está cargando una nueva página.

Si es breve, la condición debe estar en la plantilla. Es decir:

{{#if xyz}}
tu código
{{/if}}

Las plantillas de Ember son dinámicas. Si el valor cambia, el widget se ocultará.

Sí, por supuesto. :slight_smile: No tengo problemas con la sintaxis if/then; lo que pregunto es si hay alguna manera de verificar si Discourse está cargando actualmente una nueva página.

Creo que sería útil modificar la ruta de discovery utilizando la API modifyClass y luego disparar un evento personalizado.

https://api.emberjs.com/ember/3.12/classes/Route

La variable loading proviene de la ruta discovery que mencioné anteriormente. Es posible que el widget adjunto al plugin-outlet no pueda acceder a ella, ya que no se pasa como argumento; esto depende de la definición del plugin-outlet.

¡Muy bien, muchas gracias! Haré algunas indagaciones y veré qué encuentro, y actualizaré esto con una solución para la posteridad si encuentro una :slight_smile:

1 me gusta

Logré encontrar finalmente una solución. Me llevó muchísimo tiempo y, en mi opinión, vale la pena integrarla en el núcleo, ya que sinceramente parece algo que ya debería existir allí de todos modos.

Agregué el siguiente código a mi componente del tema; lo que hace es añadir una clase “loading” al body tan pronto como comienza el enrutamiento y luego la elimina en cuanto el enrutamiento finaliza. Quizás esto sea simple u obvio para quienes conocen Ember, pero me llevó un tiempo obscenamente largo (y probar un millón de cosas + leer todos los hilos que pude encontrar aquí) para descubrirlo.

Con este código del núcleo en su lugar, puedo añadir indicadores de carga y similares a mis diferentes widgets, los cuales tendrán su CSS y visibilidad controlados por si la etiqueta body tiene o no la clase CSS loading.

initialize() {
    withPluginApi("0.8.8", (api) => {
      const router = api._lookupContainer('router:main');
      router.reopen({
        addLoadingCSSClassToBody: function() {
          document.body.classList.add("loading");
        }.on('willTransition')
      });

      router.reopen({
        removeLoadingCSSClassFromBody: function() {
          document.body.classList.remove("loading");
        }.on('didTransition')
      });
    });
  },
};
1 me gusta

El código que comparto no proviene de un widget, sino de un componente que lanzamos para descarga aquí en Meta.

En él utilizamos el enrutador, junto con @discourseComputed, para verificar si la ruta ha cambiado y renderizar en consecuencia.

Puedes profundizar en el código si te interesa saber cómo funciona.

4 Me gusta