Reevaluar widgets en la cabecera al cambiar de ruta sin error

Estoy intentando sobrescribir esta plantilla de widget:

      api.reopenWidget("header-contents", {
        template: hbs`

          {{#if this.site.desktopView}}
            {{#if attrs.sidebarEnabled}}
              {{sidebar-toggle attrs=attrs}}
            {{/if}}
          {{/if}}

          {{home-logo attrs=attrs}}

          {{#if attrs.topic}}
            {{header-topic-info attrs=attrs}}
          {{else if this.siteSettings.bootstrap_mode_enabled}}
            {{#if transformed.showBootstrapMode}}
              {{header-bootstrap-mode attrs=attrs}}
            {{/if}}
          {{/if}}

          <div class="panel clearfix" role="navigation">{{yield}}</div>
        `,
      });

A pesar de que la plantilla es actualmente idéntica a la original en discourse/app/assets/javascripts/discourse/app/widgets/header-contents.js at 4aa81e709ea49e30383a3a3acd33dfedaebfc240 · discourse/discourse · GitHub

Está generando un error:

Esto es inesperado, especialmente porque en realidad no estoy “cambiando nada” (¿todavía?).

Puedo reproducir este problema incluso si esta es la única modificación.

En última instancia, la razón por la que intento cambiar esto es para poder forzar una reevaluación de esta plantilla, incluso si no me estoy moviendo dentro o fuera de una ruta de tema.

En última instancia, quiero agregar lógica para que el widget se actualice forzosamente al moverse dentro y fuera de las rutas de categorías, ya que la presentación de la ruta de mi categoría necesita ser diferente.

Entonces, una solución a esto podría ser otra forma de forzar la actualización del contenido del encabezado.

En cualquier caso, ¿esto no parece comportarse como debería?

No queremos invertir mucho tiempo aquí; los widgets no van a durar mucho más. ¿Qué personalización está intentando hacer? ¿Podemos ayudar añadiendo un punto de conexión para plugins en algún lugar (ahora tenemos la capacidad de añadir puntos de conexión normales para plugins dentro del código de los widgets)?

¿Puede compartir más de su archivo (por ejemplo, ¿de dónde se importa hbs?)?

1 me gusta

¿Y qué versión de Discourse es esta? site-header.js:337 no hace referencia actualmente a una variable ‘header’

1 me gusta

Entendido.

import { hbs } from "ember-cli-htmlbars";

Funcionalmente, estoy intentando cambiar el logo dependiendo de la ruta. En realidad, lo estoy haciendo adjuntando una imagen al logo de inicio en algunas rutas y superponiendo el logo principal. Quiero que esa lógica se reevalúe al moverse entre rutas, lo que actualmente parece funcionar al entrar y salir de las rutas de Tema, supongo porque el widget header-contents al que todo está adjunto tiene lógica que evalúa los attrs.topic que obviamente cambian cuando ocurre eso.

Mi category-logo-widget está adjunto así:

      api.decorateWidget("home-logo:after", (helper) => {
        const currentPath = helper.register
          .lookup("service:router")
          .get("_router.currentPath");

        if (
          helper.widget.currentUser &&
          !helper.widget.site.mobileView &&
          currentPath.indexOf("discovery") === -1
        ) {
          return helper.attach("category-logo-widget");
        }
      });

Lo cual funciona bien, pero no se está reevaluando entre ciertas transiciones de ruta, por lo que no cumple el requisito de ser completamente dinámico sin una recarga de página.

ooooops, este podría ser el problema, tenía la sensación de que podría serlo, pero mis pruebas obviamente fueron demasiado superficiales para descartarlo.

Veo este commit, necesitaré actualizar mi instancia de desarrollo… PERF: Memoize element references for `dockCheck` (#21079) · discourse/discourse@db16700 · GitHub

Revertiré de todos modos, ¡gracias por tu tiempo!

Este es probablemente el problema. Las ‘plantillas’ de Widget son una cosa personalizada de Discourse y se compilan de una manera totalmente diferente a las plantillas de Ember. Necesitarás importar hbs de esta manera:

Parece que tenemos un site-header:force-refresh appEvent que podrías activar en respuesta a algún otro appEvent o Ember router event:

(ejemplo de activación aquí)

3 Me gusta

Genial, gracias David, arreglaré la instalación obsoleta y también probaré tus recomendaciones aquí. Múltiples acumulaciones, ¡gracias por ayudar a aclarar!

3 Me gusta

Así que probablemente un poco gratuito, pero terminé usando tu sugerencia, con:

      api.onPageChange(url =>  {
        const applicationController = container.lookup(
          "controller:application"
        );
        applicationController.appEvents.trigger(
          "site-header:force-refresh"
        );
      });

que funcionó muy bien, aunque no se sincroniza perfectamente con la transición de la ruta, pero está bien.

¡Gracias de nuevo!

3 Me gusta

Por cierto, solo como una nota al margen, aunque la API de widgets es muy personalizada y algo complicada (especialmente las cosas de hyperscript), debo admitir que es extremadamente potente para adjuntar nuevos comportamientos a widgets existentes sin tener que anular mucho código.

Por ejemplo, he usado mucho este patrón:

api.reopenWidget('discourse-awesome-widget', {

  html(attrs, state) {
    let contents = this._super(...arguments);

    contents.unshift(h("div.my-cool-new-thing", "cool new thing"))

    return contents;
  }
});

this._super podría ser mucho código!!!

Y puede volverse mucho más inteligente que eso, hasta el punto de que he llegado a apreciarlo mucho.

Espero que la “capacidad de anulación” de lo que sea que lo reemplace sea igual de flexible y potente.

1 me gusta

La solución principal aquí serán los enchufes de complementos. Como siempre, si sientes que necesitas uno que no existe, siéntete libre de enviar una PR al núcleo :rocket:

1 me gusta

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.