Wie verwende ich api.onPageChange mit api.createWidget?

Hallo, ich versuche, ein Bildbanner zu allen Seiten hinzuzufügen, das zufällig aus zwei zufälligen Bildern auswählt. Es funktioniert, wenn ich es zum Head-Bereich meines Themes hinzufüge und die Homepage neu lade:

EDIT: Mein Versuch, der der Lösung näher kommt, ist hier:

Haben Sie eine Idee, was ich falsch mache? Danke!

Dies ist mein besserer Versuch. Wenn ich ihn ohne die Funktion api.onPageChange(() ausführe, funktioniert er, aber er randomisiert das Bild erst, wenn ich die Seite neu lade. Wenn ich die Funktion api.onPageChange(() hinzufüge, wird überhaupt kein Bild angezeigt. Irgendwelche Tipps, was ich falsch mache?

<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 „Gefällt mir“

Ich glaube, das fehlende Teil war, ein Widget-Neurendern auszulösen… wenn ich mich richtig erinnere, rendern Widgets bei Interaktion neu. Daher habe ich this.scheduleRerender(); hinzugefügt, damit es bei Seitenwechsel neu rendert.

Das funktioniert bei mir lokal:

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 „Gefällt mir“

Brillant! Vielen Dank, das hätte ich nie herausgefunden!

Hier ist der vollständige Head-Code für die Themenkomponente:

<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 „Gefällt mir“

Es ist auch erwähnenswert, dass dies eine Ember-Komponente sein könnte. Langfristig werden wir uns mehr auf Ember verlassen als auf unser benutzerdefiniertes Widget-System. Wir arbeiten noch an Ember-Updates, daher hinkt unsere Dokumentation zur Anpassung von Discourse hier etwas hinterher.

Ich habe eine Theme-Komponente zusammengestellt, die ein Beispiel dafür zeigt, wie dies als Ember-Komponente funktionieren kann: GitHub - awesomerobot/discourse-component-example

Hier sind 3 wichtige Dateien:

  1. Der Connector (/javascripts/discourse/connectors/custom-header-banner-connector.hbs)

  2. Die Komponente (/javascripts/discourse/components/custom-header-banner.js)

  3. Die Vorlage der Komponente (/javascripts/discourse/templates/components/custom-header-banner.hbs)

Der Connector ist der Ort, an dem die Komponente hinzugefügt wird, daher muss er nur <CustomHeaderBanner /> enthalten. Die Komponente ist der Ort, an dem wir Seitenänderungen (Routenänderungen) erkennen und die Logik für das zufällige Erscheinen von Bildern/Links einrichten. Die Vorlage der Komponente ist, wie die Daten in HTML präsentiert werden.

3 „Gefällt mir“

Gut zu wissen, vielen Dank auch dafür. Ich bestätige, dass es funktioniert, wenn es von Ihrem Repository als Theme-Komponente auf meiner Website installiert wird.

Könnte ich es alternativ manuell als Ember-Theme-Komponente über die Benutzeroberfläche Anpassen > Installieren > Neu erstellen und dann CSS / HTML bearbeiten hinzufügen? Das würde es einfacher machen, die Bilder und Links nach Bedarf schnell zu ändern. Ich gehe davon aus, dass der Inhalt von custom-header-banner.js unter Kopfzeile und dann \u003cCustomHeaderBanner /\u003e unter Nach Kopfzeile oder Textkörper käme, bin mir aber nicht sicher, wo der Inhalt von custom-header-banner.hbs hinzugefügt werden soll.

1 „Gefällt mir“

Das ist etwas komplizierter, um es in eine lokal installierte Theme-Komponente zu übersetzen, aber eine Möglichkeit, einem Remote-Theme etwas Flexibilität zu verleihen, wären Theme-Einstellungen (Add settings to your Discourse theme).

Dies beinhaltet das Hinzufügen einer settings.yml-Datei und das Aktualisieren einiger Werte in der Komponente und/oder der Vorlage. Dann erhalten Sie Einstellungen auf Ihrer Theme-Komponenten-Admin-Seite wie diese:

Es ist auch in Ordnung, bei der obigen Widget-Implementierung zu bleiben und über das Admin-Panel zu aktualisieren, aber wir empfehlen, wenn möglich Git zu verwenden; es ist einfacher zu teilen, wenn Sie Fehler beheben müssen, und es erleichtert die Nachverfolgung Ihrer Änderungen.

1 „Gefällt mir“

Ausgezeichnet, ich schätze Ihre geduldige und klare Erklärung sehr, es ist großartig, dass es diese Option auch gibt.

1 „Gefällt mir“

Hallo nochmal, ich versuche herauszufinden, wie ich das Widget nur auf einer bestimmten URL anzeigen kann, z. B. auf der Homepage.

Der einfache Weg ist, einfach einen Plugin-Outlet zu verwenden, der nur auf der Homepage existiert, was für meine Bedürfnisse im Moment funktioniert (speziell discovery-navigation-bar-above). Aber ich bin immer noch neugierig, wie man das programmatisch macht, auf eine Weise, die auf die spezifische Seiten-URL reagiert.

Ich habe dieses sehr hilfreiche Thema von @awesomerobot gefunden:

Ich habe versucht, dies in die Lösung vom Anfang dieses Beitrags zu integrieren:

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

Aber das bewirkt immer noch, dass das Bild auf allen Seiten angezeigt wird. Ich habe auch versucht, meine Variablen und den Code zur zufälligen Auswahl in die if-Klausel einzufügen, aber das funktioniert überhaupt nicht.

Es gibt auch den Abschnitt <script type="text/x-handlebars" ... des Beispiels, aber er scheint nur HTML zuzulassen, und ich weiß nicht, wie ich die Variablen aus dem vorherigen Skript dort hineinbekomme.

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