# 親のデータへのglimmer componentアクセスを取得

**URL:** https://meta.discourse.org/t/get-glimmer-component-access-to-stuff-from-the-parent/316898
**Category:** Development
**Created:** [2024 年 7 月 17 日午後 8:18 UTC](https://meta.discourse.org/t/get-glimmer-component-access-to-stuff-from-the-parent/316898 "2024-07-17T20:18:02Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [2024 年 7 月 17 日午後 8:18 UTC](https://meta.discourse.org/t/get-glimmer-component-access-to-stuff-from-the-parent/316898/1 "2024-07-17T20:18:02Z")

</div>

`before-topic-list-body` にコンポーネントを追加しています。このコンポーネントは、カテゴリまたはトピックからデータを取得する必要があります（どのシリアライザーがより適切かによって、必要なデータを追加します）。

数時間かけて調べましたが、お手上げ状態です。おそらく、ヒントをいただければ2〜5分で解決できる問題だと思います。

以前にこれについて考えたり聞いたりしたような気がしますが、行き詰まっています。

---

<div class="post-metadata">

### Author: ![Lilly](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/lilly/32/575047_2.png) [@Lilly](https://meta.discourse.org/u/Lilly)
#### Post date: [2024 年 7 月 18 日午前 1:45 UTC](https://meta.discourse.org/t/get-glimmer-component-access-to-stuff-from-the-parent/316898/2 "2024-07-18T01:45:56Z")

</div>

🤔 うーん

もしかしたら、このトピックに役立つものがあるかもしれません。

> [@Insert a glimmer component after first post](https://meta.discourse.org/t/insert-a-glimmer-component-after-first-post/303282):
>
> I’ve got a glimmer component. It’s working. But I need it to go after the first post in a topic. There’s no plugin outlet there. I did figure out how to insert some text in the innerHTML of the \<article\> tag, and that puts that text where I want, but there doesn’t seem to be a way to do that with a component. Am I missing something? I looked at how the adplugin inserts ads between posts, but I couldn’t quite make sense of it. export default { name: "initialize-ad-plugin", initialize(cont…

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [2024 年 7 月 18 日午後 1:49 UTC](https://meta.discourse.org/t/get-glimmer-component-access-to-stuff-from-the-parent/316898/3 "2024-07-18T13:49:10Z")

</div>

ありがとうございます、@Lilly！悪くないアイデアですが、`currentUser` はコンポーネントが挿入される場所だけでなく、ページ全体に適用されるものだと恐れていました。そして、それは正しいと思います。その方法で何が利用可能かを確認するために、公式プラグインをgrepしたところ、このサービスのリストが得られました（賢ければ、Discourseのソースでそれらを見つける方法を知っているでしょうが、私はそうではありません）：

```plaintext
  @service adminPluginNavManager;
  @service appEvents;
  @service capabilities;
  @service chatApi;
  @service composer;
      @service currentUser;
  @service currentUser;
  @service dialog;
  @service dTemplatesModal;
  @service encryptWidgetStore;
  @service hCaptchaService;
  @service imageCaptionPopup;
  @service menu;
  @service messageBus;
  @service modal;
  @service moreTopicsPreferenceTracking;
  @service presence;
  @service quickSearch;
  @service router;
  @service search;
  @service searchPreferencesManager;
  @service session;
  @service site;
  @service siteSettings;
  @service store;
  @service taskActions;
  @service toasts;
  @service upgradeStore;
  @service userFieldValidations;
  @service whosOnline;

```

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [2024 年 7 月 18 日午後 3:12 UTC](https://meta.discourse.org/t/get-glimmer-component-access-to-stuff-from-the-parent/316898/4 "2024-07-18T15:12:09Z")

</div>

見つけました。コンテキストから取得する場所は次のとおりです。

```plaintext
<RatingOne @scaleValue={{this.scaleValue}} @topic={{this.parentView._parentView.topic}} />

```

したがって、その `parentView` と `_parentView` を使用してトピックまで戻ることができます。これが私が探していた魔法です（これは別のプロジェクトの別の問題も解決すると思います）。あとは、トピックコントローラーにその内容を配置するだけです。これはすべて、私が（少なくとも大部分は）知っているはずのことです！

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [2024 年 7 月 18 日午後 3:18 UTC](https://meta.discourse.org/t/get-glimmer-component-access-to-stuff-from-the-parent/316898/5 "2024-07-18T15:18:30Z")

</div>

> [@pfaffman](#):
>
> `parentView` と `_parentView` を使ってトピックまで戻ることができるようになりました！それが私が探していた魔法です。

コンソールに非推奨メッセージが表示されましたか？ PluginOutlet からの `parentView` へのアクセスは間もなく削除されるため、表示されるはずです。実際、あまりにも非推奨であるため、UI で管理者に警告バナーが表示されるはずです 😅

警告が表示されなかった場合は、お知らせください！

（`parentView` は Ember の従来のコンポーネントシステムの一部であり、私たちはそこから移行しています）

ツリーの上位の情報にアクセスしたい場合は、引数として Plugin Outlet に渡すか、利用可能なサービス（`currentUser` や `router` など）のいずれかを使用する必要があります。

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [2024 年 7 月 18 日午後 3:28 UTC](https://meta.discourse.org/t/get-glimmer-component-access-to-stuff-from-the-parent/316898/6 "2024-07-18T15:28:25Z")

</div>

ああ、何が起こったのかわかりました。あなたは `.parentView` ではなく `._parentView` を使用しています。アンダースコア付きのバージョンを使用すると、非推奨メッセージを回避できます。しかし、それでも数週間以内に動作しなくなります。

このPRは、そのような回避策を防ぐため、`.parentView` と `._parentView` の両方で非推奨の警告が発生するようになります。

> <https://github.com/discourse/discourse/pull/27973>
>
> We'd implemented the deprecation by overriding \`get parentView\`, and storing the… real value on \`\_parentView\`. Unfortunately that meant people could access \`\_parentView\` directly, thereby bypassing the deprecation message.
> 
> This commit moves the internal storage to a private field, which cannot be accessed from outside the class. A deprecated getter for \`\_parentView\` is introduced to avoid immediate breakage for any code using this workaround.

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [2024 年 7 月 18 日午後 3:35 UTC](https://meta.discourse.org/t/get-glimmer-component-access-to-stuff-from-the-parent/316898/7 "2024-07-18T15:35:44Z")

</div>

ありがとうございます、@david！

> [@david](#):
>
> これはコンソールに非推奨メッセージを出力しましたか？

いいえ。しばらく探しても、何も表示されませんでした。`27eea3250cbde2e8bca754f445bee403c059eba3` を使用しています。

```plaintext
<RatingOne @scaleValue={{this.scaleValue}} @topic={{this.parentView._parentView.topic}} />

```

```plaintext
<td class="rating-one">
  <span class="rating-title">{{this.ratingName}}</span>
  これはトピック {{this.topic.id}} です
  これはカテゴリ {{this.topic.category.title}} (カテゴリID: {{this.topic.category_id}}) です
  {{log "rating this" this}}
  {{log "scale value" this.scaleValue}}
  {{log "rating value" this.ratingValue}}
  {{log "category" this.topic.category_id}}
    <form>
        {{!-- {{this.ratingLow}} --}}
       {{#each this.ratingOptions as |option|}}
            <input type="radio" name="rating" value={{option.value}} checked={{if (eq option.value this.ratingValue) "checked"}}> <span class="rotated-label">{{option.label}}</span>
        {{/each}}
        {{!-- {{this.ratingHigh}} --}}
    </form>
</td>

```

> [@david](#):
>
> または、利用可能なサービス（`currentUser`や`router`など）のいずれかを使用する必要があります

ああ。わかりました。では、トピックやカテゴリにアクセスするために`router`を使用できますか？私が（そう思う）やりたいことは、これらの`ratingOptions`をトピックまたはカテゴリシリアライザーに取得して、これらの複数のトピック評価をトピックリストに追加できるようにすることです。これにより、トピックに入ることなくこれらの評価を行うことができます（人々はすでにそれらに精通していると仮定されるため、トピックについて投票するためにトピックに入る必要はありません）。

> [@pfaffman](#):
>
> では、トピックやカテゴリにアクセスするために`router`を使用できますか？

うーん。それはできないようです。

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [2024 年 7 月 18 日午後 3:52 UTC](https://meta.discourse.org/t/get-glimmer-component-access-to-stuff-from-the-parent/316898/8 "2024-07-18T15:52:12Z")

</div>

> [@pfaffman](#):
>
> いいえ、しばらく探しましたが、見つかりませんでした。私は `27eea3250cbde2e8bca754f445bee403c059eba3` を使用しています。

これで修正されるはずです。[このコミット](https://github.com/discourse/discourse/commit/445951e854cbe86463d2e9f1054a902b0fee3c88) を確認してください。警告が表示されるか確認していただけますか？

> [@pfaffman](#):
>
> では、トピックやカテゴリにアクセスするために `router` を使用できますか？

理想的には、そのようなものはプラグインのアウトレットの引数として利用可能になるはずです。

上で「before-topic-list-body」について言及されていました。それにはこれらの引数がすべて含まれています。

> <https://github.com/discourse/discourse/blob/94d4b187ef9543d3a4c19ad3ce4f4f213be89d19/app/assets/javascripts/discourse/app/components/topic-list.hbs#L27C9-L37C3>

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [2024 年 7 月 18 日午後 4:56 UTC](https://meta.discourse.org/t/get-glimmer-component-access-to-stuff-from-the-parent/316898/9 "2024-07-18T16:56:11Z")

</div>

> [@david](#):
>
> Ok, that should be fixed by [this commit](https://github.com/discourse/discourse/commit/445951e854cbe86463d2e9f1054a902b0fee3c88). Can you confirm you see the warning now?

```plaintext
{{log "rating this parent" this.parentView._parentView.topic}}

```

は、醜いエラーを生成します。

```plaintext
<RatingOne @scaleValue={{this.scaleValue}} @passedRouter={{this.router}} @topic={{this.parentView}} />

```

は、エラーを生成しないようです。

> [@david](#):
>
> You mentioned ‘before-topic-list-body’ above. That has all these arguments:
> 
> [discourse/app/assets/javascripts/discourse/app/components/topic-list.hbs at 94d4b187ef9543d3a4c19ad3ce4f4f213be89d19 · discourse/discourse · GitHub](https://github.com/discourse/discourse/blob/94d4b187ef9543d3a4c19ad3ce4f4f213be89d19/app/assets/javascripts/discourse/app/components/topic-list.hbs#L27C9-L37C3)

私は本当に `above-topic-list-item` が必要ですが、あなたの素晴らしい例のおかげで、トピックが `outletArgs` にあることを発見しました。

[https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/app/components/topic-list/topic-list-item.gjs#L284](https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/app/components/topic-list/topic-list-item.gjs#L284)

ハッ！やります！

つまり、`outletArgs` は、それが `this` の中にあるということですか？（そのように見えます。`args` の中を調べる必要があると思っていました．．．）

だから、私のコネクタのhbsでは、`this.topic` にアクセスして、コンポーネントを次のように呼び出すことができます。

```plaintext
<RatingOne @name="one" @topic={{this.topic}}/>

```

そして、`RatingOne` コンポーネントのhbs（いつか `rating` に名前変更する予定です。なぜなら、値を渡す方法を見つけたからです）では、次のようにできます。

```plaintext
  This is topic {{this.topic.id}} {{this.topic.title}}
  This is category id: {{this.topic.category_id}})

```

そしてトピックの情報を取得できます！

そして今、トピックが見えるようになりました。トピックシリアライザーに引数を追加できますよね？（カテゴリに渡す方が良いかもしれませんが．．．あるいは、シリアライザーに「doTheThing」という値だけを渡して、実際の内容は `SiteSettings` から取得するかもしれません。これはサイトレベルで、カテゴリレベルではないからです。）

何か別のものが非推奨になっていない限り、あなたはそれをやったようです。本当にありがとうございます。 🍺 🍻 🥂 💰

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [2024 年 7 月 18 日午後 6:25 UTC](https://meta.discourse.org/t/get-glimmer-component-access-to-stuff-from-the-parent/316898/10 "2024-07-18T18:25:53Z")

</div>

これは「glimmerでどうやって物事を機能させるか」に関連しているので、ここに置いておきます。

トピックがレンダリングされた後にこのコードを呼び出して、`<td>` アイテムを並べ替える必要があります。`above-topic-item` を使用して、レーティングをトピックタイトルの前に配置しました。このワイルドなハックは、JavaScript の助けを借りて `<td>` アイテムを並べ替えます。

```plaintext
// document.addEventListener("DOMContentLoaded", function() {
// const table = document.querySelector('table.topic-list.ember-view');
// const rows = table.getElementsByTagName('tr');

// // todo: これはページロード時に呼び出す必要がある
// for (let row of rows) {
// const cells = Array.from(row.getElementsByTagName('td'));
// cells.sort((a, b) => {
// const orderA = parseInt(window.getComputedStyle(a).order, 10);
// const orderB = parseInt(window.getComputedStyle(b).order, 10);
// return orderA - orderB;
// });

// for (let cell of cells) {
// row.appendChild(cell);
// }
// }
// });

```

ドキュメントレベルのもの (`document-level thing`) の代わりに、`afterRender` か何かを呼び出すだけでよいと思います。ルーター (`router`) かもしれません。

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [2025 年 3 月 8 日午前 11:03 UTC](https://meta.discourse.org/t/get-glimmer-component-access-to-stuff-from-the-parent/316898/11 "2025-03-08T11:03:16Z")

</div>

ジェイ、あなたの最後の質問がこれのインスピレーションになったのではないかと疑問に思わざるを得ません。 [Upcoming topic-list changes - how to prepare themes and plugins](https://meta.discourse.org/t/upcoming-topic-list-changes-how-to-prepare-themes-and-plugins/343404?u=merefield) 🤔 ;)\n\nそして、あなたの最後の質問への答えは、最終的には「新しいAPIをチェックアウトしてください！」ということだと思います。 [Customizing the topic list](https://meta.discourse.org/t/customizing-the-topic-list/350411?u=merefield) 🚀

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [2025 年 3 月 10 日午後 3:59 UTC](https://meta.discourse.org/t/get-glimmer-component-access-to-stuff-from-the-parent/316898/12 "2025-03-10T15:59:07Z")

</div>

面白い。そして、この作業を必要としていた人物がちょうど現れた。これで、もっと簡単になるかもしれない！
