在第一篇帖子后插入一个glimmer组件

我有一个 Glimmer 组件。它能正常工作。但我需要它出现在主题的第一个帖子之后。那里没有插件出口。

我确实找到了在 <article> 标签的 innerHTML 中插入一些文本的方法,这能将文本放在我想要的位置,但似乎没有办法用组件做到这一点。

我是否遗漏了什么?

我查看了 adplugin 在帖子之间插入广告的方式,但没能完全理解。

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);
      });
    });

....

我们来添加一个!您希望放在哪里?

(有遗留的方法可以完成您正在做的事情,但当我们现代化主题视图时,它们会中断。如果我们添加一个插件出口,它将更具未来性)

2 个赞

此插件将匹配 decorateWidget("post:after 的功能,这也是 adplugin 使用的功能:

3 个赞

太棒了!抱怨一下,你就能得到!

实际上,我知道添加插件插座很容易,但当我曾经知道如何添加它们时,是在一个 hbs 文件中。

这会出现在每篇帖子之后吗?所以我需要想办法让它只出现在第一篇之后?

article:after 是我之前尝试中想出的办法。

1 个赞

帖子作为 outlet 参数之一传递,因此您可以检查 post.post_number == 1

哈哈!很高兴能回答这类问题。主题和插件使用标准 API 而不是 widget 变通方法(这些方法将在不久的将来被弃用)对每个人来说都更好。

是的,这很公平。在核心方面,在 widget 中添加它们很麻烦。但从主题/插件方面来看,它应该非常干净 :crossed_fingers:


我会尝试弄清楚那些测试失败的原因,并在明天合并 PR。(看起来额外的 html 元素会干扰 qunit 测试中一些脆弱的选择器)

2 个赞

啊哈!@outletArgs={{hash post=@data.post}}。我很有可能能弄清楚怎么做。:slight_smile:

再次感谢!

2 个赞

恐怕我在这里有点过于乐观了,@pfaffman,抱歉!我提交的 PR 会在每个帖子之间引入一个新的包装器 <div>,即使该插槽未被使用。这并不是我们真正想要做的。

或许有办法避免这个包装器……但没有什么简单的方法可以立即做到。

所以,我认为对你来说,最好的直接解决方案是复制你在 OP 中引用的 adplugin 实现。

基本上:

  1. 创建一个组件(Glimmer 或经典,无所谓),它渲染你想要的任何内容

  2. 使用 registerWidgetShim 使该组件可用作一个小部件。adplugin 示例正在创建一个名为“after-post-ad”的小部件,它渲染 PostBottomAd 组件。它将所有小部件属性 (@data) 传递到组件的 @model 参数中。

  3. 使用 api.decorateWidgetpost:after 位置渲染你的新小部件 shim。在你的例子中,如果你只想在第一个帖子显示,你可以这样做:

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

当我们最终将主题页面 Glimmer 化时,你需要移除小部件 shim/装饰,并用插件插槽替换它。这应该相当容易,因为你在组件中的所有显示逻辑都可以在插件插槽中重用。

让我们知道你的进展!很乐意帮助解答任何后续问题——我知道这里有很多活动部件。

3 个赞

我非常接近了!

唯一的问题是组件需要 currentUser,但我不知道如何传递它。这是无效的方法。

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 个赞

在您的 Banner 组件中,您可以这样注入 currentUser 服务:

class Banner extends Component {
  @service currentUser;
}

这样您就不需要从 widget 传递它了。

2 个赞

我知道传递 currentUser 是个愚蠢的想法,但我当时想不出来!

另外,如果你碰巧也需要这个,那就是

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");
        }
      });
    });
  },
};

是的!

在这种情况下,我认为您不需要导入 Service 类。只有在创建自己的服务时才需要它。您只需要 service 注入装饰器。

在最新版本的 Discourse/Ember 中,可以进一步简化,以避免需要“inject as”别名。Ember 现在可以直接将注入装饰器作为 service 提供。

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

(但旧的 { inject as service } 仍然有效,而且据我所知,Ember 没有任何计划弃用它)

编辑:但也许我可以使用 decorateWidget 而不是插件出口。。。

1 个赞

linter 也这么认为 :slight_smile:

我更喜欢这样。house ads 插件仍然是旧的方式。:slight_smile:

1 个赞

此主题在最后回复后自动关闭,已有 30 天。 不再允许回复。