¿Cómo usar api.onPageChange con api.createWidget?

Hola, estoy intentando añadir un banner de imagen a todas las páginas que elija aleatoriamente entre dos imágenes aleatorias. Funciona cuando lo añado a la sección Head de mi tema y recargo la página de inicio forzando la recarga:

EDIT: Mi intento que se acerca más a la solución está aquí:

¿Alguna idea de lo que estoy haciendo mal? ¡Gracias!

Este es mi intento más adecuado. Cuando lo ejecuto sin la función api.onPageChange(() funciona, pero no aleatoriza la imagen hasta que hago una actualización forzada de la página. Cuando agrego la función api.onPageChange(() no se muestra ninguna imagen. ¿Algún consejo sobre lo que estoy haciendo mal?

<script type="text/discourse-plugin" version="0.8">

api.onPageChange(() => {
        doStuff();
});

function doStuff() {

const h = require("virtual-dom").h;

let banners = new Array();
banners[0]="https://example.com/uploads/default/original/1X/9d9762a4129c78c478d14ff857c3bd1f2be0322a.jpg";
banners[1]="https://example.com/uploads/default/original/1X/04ede2abd9ac117c64988a5b0bcf033474381527.jpg";

let GoTo = new Array();
GoTo[0]="https://google.com";
GoTo[1]="https://brave.com";

let Number = Math.round(1 * Math.random());
let TheLink = GoTo[Number];
let TheImage = banners[Number];

  api.createWidget("top-banner-widget", {
    tagName: "div.top-banner",
    html() {
    return h("div#top-banner", [
      h(
        "a.custom-ad-link",
        { href: TheLink },
        h("img", { src: TheImage })
      )
    ]);
    }
  });
}
</script>

<script type="text/x-handlebars" data-template-name="/connectors/above-main-container/inject-widget">
  {{mount-widget widget="top-banner-widget"}}
</script>
1 me gusta

Creo que la pieza que faltaba era activar una nueva renderización del widget… si mal no recuerdo, los widgets se vuelven a renderizar al interactuar, así que he añadido this.scheduleRerender(); para que se vuelva a renderizar al cambiar de página.

Esto me funciona localmente:

api.createWidget("top-banner-widget", {
    tagName: "div.top-banner",

    html() {
        let Number = Math.round(1 * Math.random());
        
        let banners = new Array();
        banners[0]="https://placekitten.com/500/500";
        banners[1]="https://placekitten.com/500/300";

        let GoTo = new Array();
        GoTo[0]="https://google.com";
        GoTo[1]="https://brave.com";
  
        let TheLink = GoTo[Number];
        let TheImage = banners[Number];
        
        api.onPageChange(() => {
            this.scheduleRerender();
        });
  
        return h("div#top-banner", [
          h(
            "a.custom-ad-link",
            { href: TheLink },
            h("img", { src: TheImage })
          )
        ]);
    }
});
5 Me gusta

¡Genial! ¡Muchas gracias, nunca lo habría descubierto!

Aquí está el código completo de Head para el componente del tema:

<script type="text/discourse-plugin" version="0.8">

const h = require("virtual-dom").h;

api.createWidget("top-banner-widget", {
    tagName: "div.top-banner",

    html() {
        let Number = Math.round(1 * Math.random());
        
        let banners = new Array();
        banners[0]="https://example.com/uploads/default/original/1X/9d9762a4129c78c478d14ff857c3bd1f2be0322a.jpg";
        banners[1]="https://example.com/uploads/default/original/1X/04ede2abd9ac117c64988a5b0bcf033474381527.jpg";

        let GoTo = new Array();
        GoTo[0]="https://google.com";
        GoTo[1]="https://brave.com";
  
        let TheLink = GoTo[Number];
        let TheImage = banners[Number];
        
        api.onPageChange(() => {
            this.scheduleRerender();
        });
  
        return h("div#top-banner", [
          h(
            "a.custom-ad-link",
            { href: TheLink },
            h("img", { src: TheImage})
          )
        ]);
    }
});

</script>

<script type="text/x-handlebars" data-template-name="/connectors/above-main-container/inject-widget">
  {{mount-widget widget="top-banner-widget"}}
</script>
1 me gusta

También vale la pena mencionar que este podría ser un componente de Ember. A largo plazo, comenzaremos a depender más de Ember que de nuestro sistema de widgets personalizado. Todavía estamos en proceso de trabajar en las actualizaciones de Ember, por lo que nuestra documentación sobre la personalización de Discourse está un poco desactualizada en este aspecto.

He preparado un componente de tema que muestra un ejemplo de cómo esto puede funcionar como un componente de Ember: GitHub - awesomerobot/discourse-component-example

Hay 3 archivos importantes aquí:

  1. El conector (/javascripts/discourse/connectors/custom-header-banner-connector.hbs)

  2. El componente (/javascripts/discourse/components/custom-header-banner.js)

  3. La plantilla del componente (/javascripts/discourse/templates/components/custom-header-banner.hbs)

El conector es donde se agrega el componente, por lo que solo necesita contener <CustomHeaderBanner />. El componente es donde detectamos los cambios de página (cambios de ruta) y configuramos la lógica de qué imagen/enlace aparece aleatoriamente. La plantilla del componente es cómo se presentan los datos en HTML.

3 Me gusta

Ah, bueno saberlo, muchas gracias por eso también. Confirmo que funciona cuando se instala desde su repositorio como un componente de tema en mi sitio.

Alternativamente, ¿podría agregarlo manualmente como un componente de tema de Ember a través de la interfaz Personalizar > Instalar > Crear Nuevo y luego Editar CSS / HTML? Eso facilitaría el cambio rápido de las imágenes y los enlaces según sea necesario. Supongo que el contenido de custom-header-banner.js iría en Head, y luego \u003cCustomHeaderBanner /\u003e en After Header o Body, pero no estoy seguro de dónde agregar el contenido de custom-header-banner.hbs.

1 me gusta

Es un poco más complicado que eso para traducir a un componente de tema instalado localmente, pero una forma de agregar algo de flexibilidad a un tema remoto sería usar la configuración del tema (Add settings to your Discourse theme).

Eso implica agregar un archivo settings.yml y actualizar algunos valores en el componente y/o plantilla. Luego obtienes configuraciones en la página de administración de tu componente de tema como esta:

También está bien ceñirse a la implementación del widget anterior y actualizar a través del panel de administración, pero tendemos a recomendar el uso de git cuando sea posible; es más fácil de compartir si necesita solucionar problemas y facilita el seguimiento de sus cambios.

1 me gusta

Excelente, realmente aprecio tu explicación paciente y clara, es genial tener esa opción también.

1 me gusta

Hola de nuevo, estoy tratando de encontrar la mejor manera de hacer que el widget solo se muestre en una URL específica, como la página de inicio.

La forma fácil es simplemente usar un “plugin outlet” que solo existe en la página de inicio, lo que funciona para lo que necesito por ahora (específicamente, el discovery-navigation-bar-above). Pero todavía tengo curiosidad sobre cómo hacer esto programáticamente de una manera que sea sensible a la URL específica de la página.

Encontré este tema muy útil, también de @awesomerobot:

Intenté adaptar esto a la solución de la publicación anterior:

        api.onPageChange((url) => {
            if (url === "/" || url === homeRoute) {
               this.scheduleRerender();
            }
        });

Pero esto todavía hace que la imagen aparezca en todas las páginas. También intenté poner mis variables y código de selección aleatoria dentro de la cláusula if, pero eso no funciona en absoluto.

También está la sección <script type="text/x-handlebars" ... del ejemplo, pero parece que solo permite HTML, y no sé cómo pasar las variables desde el script anterior.

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