Como usar api.onPageChange com api.createWidget?

Olá, estou tentando adicionar um banner de imagem a todas as páginas que escolhe aleatoriamente entre duas imagens aleatórias. Funciona quando adiciono à seção Head do meu tema e recarrego a página inicial com força:

EDIT: Minha tentativa que chega mais perto da solução está aqui:
How to use api.onPageChange with api.createWidget? - #2 by rahim123

Alguma ideia do que estou fazendo de errado? Obrigado!

Esta é a minha tentativa mais adequada. Quando a executo sem a função api.onPageChange((), ela funciona, mas não randomiza a imagem até que eu faça uma atualização forçada da página. Quando adiciono a função api.onPageChange((), nenhuma imagem é exibida. Alguma dica sobre o que estou fazendo de errado?

<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 curtida

Acredito que a peça que faltava era acionar uma nova renderização do widget… se bem me lembro, os widgets são renderizados novamente com a interação, então adicionei this.scheduleRerender(); para que ele seja renderizado novamente na mudança de página.

Isso funciona para mim 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 curtidas

Brilhante! Muito obrigado, eu nunca teria descoberto isso!

Aqui está o código completo do Head para o componente de 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 curtida

Vale a pena mencionar que este poderia ser um componente Ember. A longo prazo, começaremos a depender mais do Ember do que do nosso sistema de widgets personalizado. Ainda estamos no processo de trabalhar nas atualizações do Ember, então nossa documentação sobre como personalizar o Discourse está um pouco atrasada nisso.

Preparei um componente de tema que mostra um exemplo de como isso pode funcionar como um componente Ember: GitHub - awesomerobot/discourse-component-example

Existem 3 arquivos importantes aqui:

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

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

  3. O template do componente (/javascripts/discourse/templates/components/custom-header-banner.hbs)

O conector é onde o componente é adicionado, então ele só precisa conter <CustomHeaderBanner />. O componente é onde detectamos mudanças de página (mudanças de rota) e configuramos a lógica para qual imagem/link aparece aleatoriamente. O template do componente é como os dados são apresentados em HTML.

3 curtidas

Ah, bom saber, muito obrigado por isso também. Confirmo que funciona quando instalado a partir do seu repositório como um componente de tema no meu site.

Alternativamente, eu poderia adicioná-lo manualmente como um componente de tema Ember através da interface Personalizar > Instalar > Criar Novo e, em seguida, Editar CSS / HTML? Isso facilitaria a alteração rápida das imagens e links conforme necessário. Presumo que o conteúdo de custom-header-banner.js iria para Cabeçalho, e então \u003cCustomHeaderBanner /\u003e em Após Cabeçalho ou Corpo, mas não tenho certeza onde adicionar o conteúdo de custom-header-banner.hbs.

1 curtida

É um pouco mais complicado do que isso para traduzir para um componente de tema instalado localmente, mas uma maneira de adicionar alguma flexibilidade a um tema remoto seria usar configurações de tema (Add settings to your Discourse theme).

Isso envolve adicionar um arquivo settings.yml e atualizar alguns valores no componente e/ou template. Então você obtém configurações na sua página de administração do componente de tema como esta:

Também não há problema em manter a implementação do widget acima e atualizar pelo painel de administração, mas tendemos a recomendar o uso do git quando possível; é mais fácil de compartilhar se você precisar solucionar problemas e facilita o rastreamento de suas alterações.

1 curtida

Excelente, realmente aprecio sua explicação paciente e clara, ótimo ter essa opção também.

1 curtida

Olá novamente, estou tentando descobrir a melhor maneira de fazer o widget aparecer apenas em uma URL específica, como a página inicial.

A maneira fácil é simplesmente usar um outlet de plugin que existe apenas na página inicial, o que funciona para o que preciso por enquanto (especificamente, o discovery-navigation-bar-above). Mas ainda estou curioso sobre como fazer isso programaticamente de uma forma que seja sensível à URL da página específica.

Encontrei este tópico muito útil, também de @awesomerobot:

Tentei adaptar isso à solução do início deste post:

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

Mas isso ainda faz com que a imagem apareça em todas as páginas. Também tentei colocar minhas variáveis e código de seleção aleatória dentro da cláusula if, mas isso não funciona de forma alguma.

Há também a seção <script type="text/x-handlebars" ... do exemplo, mas parece permitir apenas HTML, e não sei como obter as variáveis para ela do script anterior.

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