Comment utiliser api.onPageChange avec api.createWidget ?

Salut, j’essaie d’ajouter une bannière d’image à toutes les pages qui choisit aléatoirement parmi deux images aléatoires. Cela fonctionne lorsque je l’ajoute à la section Head de mon thème et que je recharge la page d’accueil :

EDIT : Ma tentative qui se rapproche le plus de la solution est ici :

Des idées sur ce que je fais de mal ? Merci !

Ceci est ma tentative plus sérieuse. Lorsque je l’exécute sans la fonction api.onPageChange((), cela fonctionne, mais ne randomise pas l’image avant que je ne fasse un actualisation forcée de la page. Lorsque j’ajoute la fonction api.onPageChange((), aucune image ne s’affiche. Des conseils sur ce que je fais 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 « J'aime »

Je pense que la pièce manquante était de déclencher un nouveau rendu du widget… si je me souviens bien, les widgets se rendent à nouveau lors d’une interaction, j’ai donc ajouté this.scheduleRerender(); pour qu’il se rende à nouveau lors du changement de page.

Cela fonctionne pour moi localement :

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 « J'aime »

Brillant ! Merci beaucoup, je n’aurais jamais trouvé ça !

Voici le code Head complet pour le composant de thème :

<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 « J'aime »

Il convient également de mentionner que cela pourrait être un composant Ember. À long terme, nous allons commencer à nous appuyer davantage sur Ember que sur notre système de widgets personnalisé. Nous sommes toujours en train de travailler sur les mises à jour d’Ember, donc notre documentation sur la personnalisation de Discourse est un peu en retard sur ce point.

J’ai créé un composant de thème qui montre un exemple de la façon dont cela peut fonctionner en tant que composant Ember : GitHub - awesomerobot/discourse-component-example

Il y a 3 fichiers importants ici :

  1. Le connecteur (/javascripts/discourse/connectors/custom-header-banner-connector.hbs)

  2. Le composant (/javascripts/discourse/components/custom-header-banner.js)

  3. Le modèle du composant (/javascripts/discourse/templates/components/custom-header-banner.hbs)

Le connecteur est l’endroit où le composant est ajouté, donc il ne doit contenir que <CustomHeaderBanner />. Le composant est l’endroit où nous détectons les changements de page (changements de route) et mettons en place la logique pour déterminer quelle image/lien apparaît aléatoirement. Le modèle du composant est la manière dont les données sont présentées en HTML.

3 « J'aime »

Ah, bon à savoir, merci beaucoup pour cela également. Je confirme que cela fonctionne lorsqu’il est installé à partir de votre dépôt en tant que composant de thème sur mon site.

Alternativement, puis-je l’ajouter manuellement en tant que composant de thème Ember via l’interface Personnaliser > Installer > Créer nouveau puis Modifier CSS / HTML ? Cela permettrait de changer rapidement les images et les liens si nécessaire. Je suppose que le contenu de custom-header-banner.js irait sous Head, puis \u003cCustomHeaderBanner /\u003e dans After Header ou Body, mais je ne suis pas sûr où ajouter le contenu de custom-header-banner.hbs.

1 « J'aime »

C’est un peu plus compliqué que cela pour traduire vers un composant de thème installé localement, mais une façon d’ajouter de la flexibilité à un thème distant serait d’utiliser les paramètres de thème (Add settings to your Discourse theme).

Cela implique d’ajouter un fichier settings.yml et de mettre à jour quelques valeurs dans le composant et/ou le modèle. Ensuite, vous obtenez des paramètres sur votre page d’administration de composant de thème comme ceci :

Il est également possible de conserver l’implémentation du widget ci-dessus et de mettre à jour via le panneau d’administration, mais nous avons tendance à recommander l’utilisation de git lorsque c’est possible ; il est plus facile à partager si vous avez besoin de dépanner, et cela facilite le suivi de vos modifications.

1 « J'aime »

Excellent, j’apprécie vraiment votre explication patiente et claire, c’est formidable d’avoir cette option également.

1 « J'aime »

Salut encore, j’essaie de trouver la meilleure façon de faire en sorte que le widget ne s’affiche que sur une URL spécifique, comme la page d’accueil.

La façon simple est d’utiliser une sortie de plugin qui n’existe que sur la page d’accueil, ce qui fonctionne pour ce dont j’ai besoin pour l’instant (spécifiquement, le discovery-navigation-bar-above). Mais je suis toujours curieux de savoir comment faire cela par programmation d’une manière qui soit sensible à l’URL de la page spécifique.

J’ai trouvé ce sujet très utile, également par @awesomerobot :

J’ai essayé d’adapter cela à la solution de plus tôt dans ce post :

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

Mais cela fait toujours apparaître l’image sur toutes les pages. J’ai aussi essayé de mettre mes variables et mon code de sélection aléatoire à l’intérieur de la clause if, mais cela ne fonctionne pas du tout.

Il y a aussi la section <script type="text/x-handlebars" ... de l’exemple, mais elle ne semble autoriser que le HTML, et je ne sais pas comment y intégrer les variables du script précédent.

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