Fügen Sie ein Glimmer-Komponente nach dem ersten Beitrag ein

Ich habe eine Glimmer-Komponente. Sie funktioniert. Aber ich brauche sie nach dem ersten Beitrag in einem Thema. Dort gibt es keinen Plugin-Outlet.

Ich habe herausgefunden, wie man Text in das innerHTML des \u003carticle\u003e-Tags einfügt, und das platziert den Text dort, wo ich ihn haben möchte, aber es scheint keine Möglichkeit zu geben, dies mit einer Komponente zu tun.

Übersehe ich etwas?

Ich habe mir angesehen, wie das AdPlugin Anzeigen zwischen Beiträgen einfügt, aber ich konnte es nicht ganz verstehen.

export default {
  name: "initialize-ad-plugin",
  initialize(container) {
    registerWidgetShim(
      "after-post-ad",
      "div.widget-connector",
      hbs`<PostBottomAd @model={{@data}} />`
    );

    withPluginApi("0.1", (api) => {
      api.decorateWidget("post:after", (helper) => {
        return helper.attach("after-post-ad", helper.widget.model);
      });
    });

....

Fügen wir eine hinzu! Wo möchten Sie sie haben?

(Es gibt ältere Wege, um das zu erreichen, was Sie tun, aber diese werden brechen, wenn wir die Themenansicht modernisieren. Wenn wir eine Plugin-Ausgabe hinzufügen, wird sie zukunftssicherer sein)

2 „Gefällt mir“

Diese Auslassung würde der Funktionalität von decorateWidget("post:after entsprechen, die das Adplugin verwendet:

3 „Gefällt mir“

Das ist großartig! Jammern und du wirst bekommen!

Eigentlich “weiß” ich, dass es “einfach” ist, Plugin-Outlets hinzuzufügen, aber als ich so ungefähr wusste, wie man sie hinzufügt, war es in einer hbs-Datei.

Wird das nach jedem Beitrag sein? Ich muss also irgendeine Magie herausfinden, um es nur nach dem ersten anzuzeigen?

article:after ist das, was ich bei früheren Versuchen erdacht hatte.

1 „Gefällt mir“

Der Beitrag wird als eines der Outlet-Argumente übergeben, sodass Sie post.post_number == 1 überprüfen können

Haha! Ich helfe immer gerne bei solchen Fragen. Es ist für alle besser, wenn wir Themes und Plugins über Standard-APIs wie diese nutzen können, anstatt Widget-Workarounds (die in nicht allzu ferner Zukunft veraltet sein werden).

Ja, das ist fair. Das Hinzufügen innerhalb von Widgets ist auf der Core-Seite eine Qual. Aber von der Theme-/Plugin-Seite sollte es super sauber sein :crossed_fingers:


Ich werde versuchen, die Testfehler herauszufinden und den PR morgen zusammenzuführen. (Es sieht so aus, als ob das zusätzliche HTML-Element einige fragile Selektoren in den Qunit-Tests durcheinander bringt)

2 „Gefällt mir“

Aha! @outletArgs={{hash post=@data.post}}. Es besteht eine gute Chance, dass ich herausfinden kann, wie das geht. :slight_smile:

Nochmals vielen Dank!

2 „Gefällt mir“

Ich fürchte, ich war hier etwas zu optimistisch, @pfaffman, Entschuldigung! Der PR, den ich gemacht habe, würde einen neuen Wrapper <div> zwischen jedem einzelnen Beitrag einführen, auch wenn der Outlet nicht verwendet wurde. Das wollen wir eigentlich nicht tun.

Es mag Wege geben, den Wrapper zu vermeiden … aber nichts Einfaches, das wir sofort tun können.

Daher denke ich, dass die beste sofortige Lösung für Sie darin besteht, die Implementierung des Adplugins zu kopieren, auf die Sie im OP verwiesen haben.

Im Wesentlichen:

  1. Erstellen Sie eine Komponente (Glimmer oder klassisch, das spielt keine Rolle), die das gewünschte rendert.

  2. Verwenden Sie registerWidgetShim, um diese Komponente als Widget verfügbar zu machen. Das Adplugin-Beispiel erstellt ein Widget namens “after-post-ad”, das die Komponente PostBottomAd rendert. Es übergibt alle Widget-Attribute (@data) an das @model-Argument der Komponente.

  3. Verwenden Sie api.decorateWidget, um Ihren neuen Widget-Shim in der Position post:after zu rendern. In Ihrem Fall, da Sie ihn nur beim ersten Beitrag wünschen, könnten Sie etwas wie folgt tun:

    api.decorateWidget("post:after", (helper) => {
      if (helper.widget.model.post_number === 1) {
        return helper.attach("my-widget-shim");
      }
    });
    

Wenn wir die Topic-Seite irgendwann mit Glimmer versehen, müssen Sie den Widget-Shim/die Dekoration entfernen und durch einen Plugin-Outlet ersetzen. Das sollte ziemlich einfach sein, da Ihre gesamte Anzeigelogik in der Komponente im Plugin-Outlet wiederverwendbar sein wird.

Lassen Sie uns wissen, wie es Ihnen ergeht! Gerne helfe ich Ihnen bei weiteren Fragen - ich weiß, dass hier viele bewegliche Teile im Spiel sind.

3 „Gefällt mir“

Ich bin so nah dran!

Das einzige Problem ist, dass die Komponente currentUser benötigt und ich nicht herausfinden kann, wie ich sie übergeben kann. Hier ist, was nicht funktioniert.

import { hbs } from "ember-cli-htmlbars";
import { withPluginApi } from "discourse/lib/plugin-api";
import Site from "discourse/models/site";
import { registerWidgetShim } from "discourse/widgets/render-glimmer";
import Banner from "../components/banner";

export default {
  name: "initialize-banner-widget",
  initialize(container) {
    registerWidgetShim(
      "geo-banner-widget",
      "div.widget-connector",
      hbs`<Banner @currentUser={{currentUser}} />`
    );

    // withPluginApi("0.1", (api) => {
    //   console.log("doing plugin");
    //   api.decorateWidget("post:after", (helper) => {
    //     return helper.attach("geo-banner-widget", helper.widget.model);
    //   });
    // });

    withPluginApi("0.1", (api) => {
      const currentUser = container.lookup("service:current-user");
      api.decorateWidget("post:after", (helper) => {
        console.log(`decorate widget ${currentUser.username}`, );
        if(helper.widget.model.post_number === 1){
          return helper.attach("geo-banner-widget", { currentUser });
        }
      });
    });
  },
};
1 „Gefällt mir“

In Ihrer Banner-Komponente können Sie den currentUser-Dienst wie folgt injizieren:

class Banner extends Component {
  @service currentUser;
}

dann müssen Sie ihn nicht vom Widget aus übergeben.

2 „Gefällt mir“

Ich wusste, dass es dumm war, currentUser zu übergeben, aber ich konnte das nicht herausfinden!

Das andere Stück, für den unwahrscheinlichen Fall, dass es jemand anderem nützlich ist, ist

import Service, { inject as service } from "@ember/service";
import { hbs } from "ember-cli-htmlbars";
import { withPluginApi } from "discourse/lib/plugin-api";
import { registerWidgetShim } from "discourse/widgets/render-glimmer";

export default {
  name: "initialize-banner-widget",
  initialize(container) {
    registerWidgetShim(
      "geo-banner-widget",
      "div.widget-connector",
      hbs`<Banner/>`
    );

    withPluginApi("0.1", (api) => {
      api.decorateWidget("post:after", (helper) => {
        const currentUser = container.lookup("service:current-user");
        if(helper.widget.model.post_number === 1){
          return helper.attach("geo-banner-widget");
        }
      });
    });
  },
};

Yup!

In diesem Fall denke ich nicht, dass Sie die Klasse Service importieren müssen. Das wäre nur nötig, wenn Sie Ihren eigenen Service erstellen würden. Sie benötigen nur den service-Injektionsdekorator.

Und in der neuesten Version von Discourse/Ember kann dies sogar noch weiter vereinfacht werden, um die inject as-Alias zu vermeiden. Ember macht den Injektionsdekorator jetzt direkt als service verfügbar.

import { service } from "@ember/service";

(aber das alte { inject as service } funktioniert immer noch, und ich bin mir keiner Pläne bewusst, es in Ember zu verwerfen)

EDIT: Aber vielleicht kann ich decorateWidget anstelle eines Plugin-Outlets verwenden. . .

1 „Gefällt mir“

Das denkt der Linter auch :slight_smile:

Das gefällt mir besser. Das House Ads Plugin macht es immer noch auf die alte Weise. :slight_smile:

1 „Gefällt mir“

Dieses Thema wurde 30 Tage nach der letzten Antwort automatisch geschlossen. Neue Antworten sind nicht mehr möglich.