this.modal.show() を介して Glimmer コンポーネント (.gjs) をモーダルとして表示しようとすると、持続的なレンダリングエラーが発生しています。モーダルは、post-menu-buttons 値トランスフォーマーを介して投稿メニューに追加された別の GJS コンポーネントからトリガーされます。Discourse v3.5.0.beta3-dev を実行しています。
api.registerValueTransformer("post-menu-buttons", ...) を使用して投稿メニューにボタンを追加しようとしています。このボタンをクリックすると、this.modal.show(FeedbackFormModal, ...) を使用して別の GJS コンポーネント (FeedbackFormModal) によって定義されたモーダルが開くはずです。
ボタンがクリックされ、this.modal.show() が呼び出されると、FeedbackFormModal のレンダリングプロセス中に発生しているように見える次のエラーでアプリケーションがクラッシュします。
エラーが発生しました:
- レンダリング中:
-トップレベル
アプリケーション
(不明なテンプレート専用コンポーネント)
DiscourseRoot
ModalContainer
FeedbackFormModal
DModal
conditional-in-element:ConditionalInElement
(不明なテンプレート専用コンポーネント) index.js:3970:18
エラーが発生しました: index.js:3377:16
未処理 (Promise 内) Error: 値をヘルパーとして使用しようとしましたが、オブジェクトまたは関数ではありませんでした。ヘルパー定義は、関連付けられたヘルパーマネージャーを持つオブジェクトまたは関数である必要があります。値は次のとおりでした:undefined
Ember 2
source chunk.8d6366d70b85d1b69fdc.d41d8cd9.js:89256
Ember 2
source chunk.8d6366d70b85d1b69fdc.d41d8cd9.js:90066
Ember 4
source chunk.8d6366d70b85d1b69fdc.d41d8cd9.js:90164
source chunk.8d6366d70b85d1b69fdc.d41d8cd9.js:89224
Ember 2
source chunk.8d6366d70b85d1b69fdc.d41d8cd9.js:90163
Ember 2
source chunk.8d6366d70b85d1b69fdc.d41d8cd9.js:90284
Ember 2
source chunk.8d6366d70b85d1b69fdc.d41d8cd9.js:92117
Ember 12
source chunk.8d6366d70b85d1b69fdc.d41d8cd9.js:94577
source chunk.8d6366d70b85d1b69fdc.d41d8cd9.js:96288
Ember 34
show modal.js:73
openFeedbackModal leave-feedback-button.js:102 // 行番号は若干異なる場合があります
_triggerAction d-button.gjs:138
Ember 10
このエラーは、FeedbackFormModal テンプレートが、インポートされたコアコンポーネント (<DModal>, <DButton>) と標準の組み込みヘルパー (if, on など) のみを含むように最小限に削減された場合でも発生します。
参照用にコードを以下に貼り付けます。
plugin.rb
# frozen_string_literal: true
# name: my-plugin
module ::MyPlugin
# ... 定数 ...
end
require_relative "lib/my_plugin/engine"
after_initialize do
# 依存関係のロード (require_dependency と File.expand_path を使用)
require_dependency File.expand_path('app/controllers/my_plugin/my_controller.rb', __dir__)
require_dependency File.expand_path('app/models/my_plugin/my_model.rb', __dir__)
# ... その他の依存関係 ...
# User にメソッドを追加 (prepend が失敗したため class_eval を使用)
::User.class_eval do
# my_custom_stat などのヘルパーメソッドを定義
def my_custom_stat; # ... 実装 ...; end
public :my_custom_stat
# ... その他のメソッド ...
end
# Guardian 拡張機能のプリペンド (もしあれば)
# ::Guardian.prepend(MyPlugin::GuardianExtensions)
# シリアライザーの変更
reloadable_patch do |plugin|
# シリアライザーに属性を追加、例:
add_to_serializer(:post, :some_flag_for_button) do
# ボタンを表示するかどうかを決定するロジック
true # 例
end
# ... その他のシリアライザーの追加 ...
end
end
assets/javascripts/discourse/initializers/my-plugin-outlets.js
import { apiInitializer } from "discourse/lib/api";
import { hbs } from "ember-cli-htmlbars";
import LeaveFeedbackButton from "../components/leave-feedback-button"; // ボタンコンポーネント
// ... 他のアウトレットの他のコンポーネントをインポート ...
export default apiInitializer("1.13.0", (api) => {
// Post Menu Button に Value Transformer を使用
api.registerValueTransformer("post-menu-buttons", ({ value: dag, context }) => {
const { post } = context;
// post.some_flag_for_button に基づいてボタンをレンダリングするかどうかを決定するロジック
const shouldRenderButton = post?.some_flag_for_button; // 例のフラグ
if (shouldRenderButton) {
dag.add("leaveMyPluginFeedback", LeaveFeedbackButton, {
after: "like",
args: { post: post },
});
}
return dag;
});
// ... 他の UI 要素の renderInOutlet ...
});
ボタンコンポーネント (assets/javascripts/discourse/components/leave-feedback-button.gjs)
import Component from "@glimmer/component";
import { action } from "@ember/object";
import { service } from "@ember/service";
import DButton from "discourse/components/d-button";
import FeedbackFormModal from "./feedback-form-modal"; // モーダルコンポーネント
export default class LeaveFeedbackButton extends Component {
@service modal;
@service appEvents; // エラー表示に使用
// Args: post
get buttonLabel() { return "Action Button"; } // ハードコーディング
get buttonTitle() { return "Perform Action"; } // ハードコーディング
@action
openFeedbackModal() {
console.log("Opening Modal...");
try {
// テスト用の簡略化されたモデル
const modelData = { post_id: this.args.post.id };
this.modal.show(FeedbackFormModal, { model: modelData });
} catch(e) {
console.error("Error showing modal", e);
this.appEvents.trigger("show:error", "Error opening modal.");
}
}
<template>
<DButton
class="btn-default my-plugin-btn"
@action={{this.openFeedbackModal}}
@icon="star" {{!-- 例のアイコン --}}
@label={{this.buttonLabel}}
title={{this.buttonTitle}}
/>
</template>
}
モーダルコンポーネント (assets/javascripts/discourse/components/feedback-form-modal.gjs - 超簡略化版)
import Component from "@glimmer/component"; // これがインポートされていることを確認してください
// 簡略化版で必要ない場合は、tracked, action, service などを削除
import DModal from "discourse/components/d-modal"; // これがインポートされていることを確認してください
import DButton from "discourse/components/d-button"; // これがインポートされていることを確認してください
import { on, preventDefault } from '@ember/modifier'; // 使用する場合は組み込みをインポート
export default class FeedbackFormModal extends Component {
// 簡略化されたテンプレートに必要な最小限の JS
// テンプレートで必要な例のゲッター
get modalTitle() { return "My Modal Title"; } // ハードコーディング
get cancelLabel() { return "Cancel"; }
get submitLabel() { return "Submit"; }
// ボタンで必要なダミーアクション
@action submitFeedback() { console.log("Dummy submit"); }
{{!-- エラーが発生する超簡略化されたテンプレート --}}
<template>
<DModal @title={{this.modalTitle}} @closeModal={{@closeModal}} class="feedback-form-modal">
<:body>
<p>--- MINIMAL MODAL TEST ---</p>
{{#if this.errorMessage}} {{!-- 組み込み 'if' を使用 --}}
<div class="alert alert-error" role="alert">{{this.errorMessage}}</div>
{{/if}}
</:body>
<:footer>
<DButton @action={{@closeModal}} class="btn-flat"> {{this.cancelLabel}} </DButton>
<DButton @action={{this.submitFeedback}} class="btn-primary" @icon={{if this.isSubmitting "spinner"}}> {{!-- 組み込み 'if' を使用 --}}
{{this.submitLabel}}
</DButton>
</:footer>
</DModal>
</template>
}
registerValueTransformer("post-menu-buttons", ...) を介して追加されたコンポーネントからトリガーされる this.modal.show() を使用して、 <DModal>/<DButton> のようなインポートされたコアコンポーネントと if のような組み込みヘルパーのみを含む超簡略化された GJS コンポーネントテンプレートをレンダリングする場合でも、Attempted to use a value as a helper... undefined というエラーが発生し続けることを考えると、何が原因である可能性がありますか?
最近の Discourse バージョン (特に 3.5.0.beta3-dev) では、このようにトリガーされたモーダルでのヘルパー/コンポーネントスコープ解決に既知の問題または制限はありますか? GJS で投稿メニューボタンからモーダルフォームを表示するための代替推奨パターンはありますか?
何か手がかりがあれば幸いです!

