ルート変更時にヘッダーのウィジェットをエラーなく再評価する

このウィジェットテンプレートをオーバーライドしようとしています。

      api.reopenWidget("header-contents", {
        template: hbs`

          {{#if this.site.desktopView}}
            {{#if attrs.sidebarEnabled}}
              {{sidebar-toggle attrs=attrs}}
            {{/if}}
          {{/if}}

          {{home-logo attrs=attrs}}

          {{#if attrs.topic}}
            {{header-topic-info attrs=attrs}}
          {{else if this.siteSettings.bootstrap_mode_enabled}}
            {{#if transformed.showBootstrapMode}}
              {{header-bootstrap-mode attrs=attrs}}
            {{/if}}
          {{/if}}

          <div class="panel clearfix" role="navigation">{{yield}}</div>
        `,
      });

このテンプレートは、discourse/app/assets/javascripts/discourse/app/widgets/header-contents.js at 4aa81e709ea49e30383a3a3acd33dfedaebfc240 · discourse/discourse · GitHub の元のテンプレートと全く同じであるにもかかわらず、エラーが発生しています。

特に、まだ何も「変更」していないのに、これは予期せぬことです。

これが唯一の変更であっても、この問題が再現できることを確認しています。

最終的にこれを変更しようとしているのは、トピックのルートに出入りしていなくても、このテンプレートの再評価を強制できるようにするためです。

最終的には、カテゴリのルート表示を異なるものにする必要があるため、カテゴリのルートに出入りする際にヘッダーが強制的に更新されるようにロジックを追加したいと考えています。

いずれにしても、これは予期される動作とは異なるようです。

ウィジェットはもう長くは使われないので、あまり時間をかけたくありません。どのようなカスタマイズをご希望ですか?(ウィジェットコード内に通常のプラグインアウトレットを追加できるようになりました。)プラグインアウトレットをどこかに追加することで、お手伝いできますか?

ファイルをもっと共有していただけますか?(例:hbs はどこからインポートされていますか?)

「いいね!」 1

Discourseのどのバージョンですか? site-header.js:337 は現在「header」変数に参照されていません。

「いいね!」 1

承知いたしました。

import { hbs } from "ember-cli-htmlbars";

実際には、ルートに応じてロゴを切り替えたいと考えています。具体的には、一部のルートでホームロゴに画像を追加し、プライマリロゴを重ねることで実現しています。このロジックがルート間を移動する際に再評価されることを望んでいます。これは現在、Topicルートに出入りする際には機能しているようです。おそらく、すべてがアタッチされている header-contents ウィジェットに attrs.topic を評価するロジックがあり、これが変更されると当然ながら変化するからです。

私の category-logo-widget は次のようにアタッチされています。

      api.decorateWidget("home-logo:after", (helper) => {
        const currentPath = helper.register
          .lookup("service:router")
          .get("_router.currentPath");

        if (
          helper.widget.currentUser &&
          !helper.widget.site.mobileView &&
          currentPath.indexOf("discovery") === -1
        ) {
          return helper.attach("category-logo-widget");
        }
      });

これはうまく機能しますが、特定のルート遷移の間で再評価されず、ページをリロードせずに完全に動的に要件を満たしていません。

おっと、これが問題の原因かもしれません。その可能性はあると思っていましたが、私のテストは明らかに表面的すぎて、これを却下するには不十分でした。

このコミットを見つけました。開発インスタンスを更新する必要があります… PERF: Memoize element references for `dockCheck` (#21079) · discourse/discourse@db16700 · GitHub

いずれにしても元に戻します。お時間をいただきありがとうございました!

これは問題である可能性が高いです。ウィジェットの「テンプレート」はDiscourse独自の機能であり、Emberのテンプレートとは全く異なる方法でコンパイルされます。hbsは次のようにインポートする必要があります。

他のappEventまたはEmberルーターイベントに応答してトリガーできるsite-header:force-refresh appEventがあるようです。

(トリガーの例はこちら

「いいね!」 3

素晴らしい、ありがとうデイビッド。古いインストールを修正し、ここでのあなたの推奨事項も試してみます。複数の問題が重なっていたので、解決に役立ててくれてありがとう!

「いいね!」 3

おそらく少し過剰ですが、あなたの提案を使用しました。

      api.onPageChange(url =>  {
        const applicationController = container.lookup(
          "controller:application"
        );
        applicationController.appEvents.trigger(
          "site-header:force-refresh"
        );
      });

これでうまく動作しましたが、ルート遷移とは完全に同期しませんが、問題ありません。

改めて、ありがとうございました!

「いいね!」 3

ちなみに、ウィジェットAPIは非常に特殊で少し扱いにくい(特にハイパースクリプトの部分)ですが、多くのコードをオーバーライドする必要なく、既存のウィジェットに新しい動作をアタッチできるのは非常に強力だと認めざるを得ません。

例えば、このパターンを多用しました。

api.reopenWidget('discourse-awesome-widget', {

  html(attrs, state) {
    let contents = this._super(...arguments);

    contents.unshift(h("div.my-cool-new-thing", "cool new thing"))

    return contents;
  }
});

this._super はかなりのコード量になる可能性があります!

そして、それ以上に巧妙なこともできるため、私はそれを高く評価するようになりました。

それが置き換わるものの「オーバーライド可能性」も同様に柔軟で強力であることを願っています。

「いいね!」 1

ここでの主な解決策はプラグインのアウトレットになります。いつものように、存在しないと思うものが必要だと感じた場合は、コアにPRを作成してください :rocket:

「いいね!」 1

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