插件模态组件导入错误 - 遵循官方文档但仍出现错误

Problem Summary

I’m developing a Discourse plugin that adds a toolbar button to open a modal form. I’ve followed the official DModal API migration documentation step-by-step, but I’m still getting module import errors and the “modal needs updating” warning. Need guidance on what I’m missing.

A quick note: I don’t know how to program, this plugin was created entirely with the help of AI.

Current Errors

Error 1 - Module Import:

Uncaught (in promise) Error: Could not find module `discourse/components/modal/lottery-form-modal` imported from `discourse/plugins/discourse-lottery-v3/discourse/initializers/lottery-toolbar`

Error 2 - Legacy Modal Warning:

Error: the 'lottery-form' modal needs updating to work with the latest version of Discourse. See https://meta.discourse.org/t/268057.

Error 3 - Deprecation Notice:

Deprecation notice: Defining modals using a controller is no longer supported. Use the component-based API instead. (modal: lottery-form) [deprecated since Discourse 3.1] [removal in Discourse 3.2]

Official Documentation I’ve Followed

I’ve carefully studied and implemented based on these official resources:

  1. Converting modals from legacy controllers to new DModal component API

    • URL: https://meta.discourse.org/t/268057
    • Followed all 4 steps: moved files to /components/modal/, updated JS to extend Component, updated template to use <DModal>, updated show calls to use modal.show()
  2. Using the DModal API to render Modal windows

    • URL: https://meta.discourse.org/t/268304
    • Implemented DModal with proper @closeModal, @title, and named blocks
  3. Discourse Core Plugin API

    • Source: https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/app/lib/plugin-api.gjs
    • Used api.onToolbarCreate() and modal service injection
  4. Discourse Developer Docs - Converting Modals

    • URL: https://github.com/discourse/discourse-developer-docs/blob/main/docs/03-code-internals/10-converting-modals.md
    • Cross-referenced migration steps

What I’m Trying to Do

  • Add a toolbar button in the composer
  • Click button opens a modal form
  • User fills form and clicks submit
  • Modal closes and inserts content into composer

What I’ve Tried

Approach 1: Dynamic Import + Modal Service (Current)

  • Getting module import error

Approach 2: showModal() with Controller

  • Getting deprecation warnings about legacy controllers

Approach 3: Static Import

  • Also tried static imports but same module resolution issues

File structure:

discourse-lottery-v3/
├── plugin.rb
└── assets/javascripts/discourse/
    ├── initializers/
    │   └── lottery-toolbar.js
    └── components/modal/
        ├── lottery-form-modal.js
        └── lottery-form-modal.hbs

Toolbar button code:

// assets/javascripts/discourse/initializers/lottery-toolbar.js
import { withPluginApi } from "discourse/lib/plugin-api";

export default {
  name: "lottery-toolbar",
  initialize() {
    withPluginApi("1.0.0", (api) => {
      api.onToolbarCreate((toolbar) => {
        toolbar.addButton({
          id: "lottery-insert",
          group: "extras",
          icon: "dice",
          title: "Insert Lottery",
          perform: () => {
            const modal = api.container.lookup("service:modal");

            // This line causes the import error:
            import("discourse/components/modal/lottery-form-modal").then((module) => {
              const LotteryFormModal = module.default;
              modal.show(LotteryFormModal, { model: {} });
            });
          }
        });
      });
    });
  }
};

Modal component:

// assets/javascripts/discourse/components/modal/lottery-form-modal.js
import Component from "@ember/component";
import { tracked } from "@glimmer/tracking";
import { action } from "@ember/object";

export default class LotteryFormModal extends Component {
  @tracked inputValue = "";

  @action
  submit() {
    // Handle form submission
    this.args.closeModal();
  }
}

Modal template:

{{! assets/javascripts/discourse/components/modal/lottery-form-modal.hbs }}
<DModal @title="My Modal" @closeModal={{this.args.closeModal}} class="my-modal">
  <:body>
    <input value={{this.inputValue}} />
  </:body>
  <:footer>
    <button {{on "click" this.submit}}>Submit</button>
  </:footer>
</DModal>

Questions

Based on all the code, errors, and background information provided above, how should I modify my code to correctly implement my feature?

Any guidance on the correct implementation approach would be greatly appreciated

Try importing it from ../components/modal/lottery-form-modal instead.

When you start your import with discourse, it will look for the file and directory in the Discourse codebase, not your own project.

For example, your line:

imports this from app/assets/javascripts/discourse/app/lib/plugin-api.gjs in the Discourse codebase.

As an example on how you could do this, see @abroun_beholder’s GitHub - Beholder-Vision/discourse-insert-model-3d: A Discourse theme component for adding 3D models to topics.

Thank you! That explanation about the import paths was exactly what I needed. The modal is working perfectly now. Really appreciate your help!

2 个赞

No problem, happy to help!