הוספת טופס לפלאגין

סיכום מבוסס בינה מלאכותית

alangibson is developing a Discourse plugin to add a form above the topic timeline that submits an email to a controller. They encountered an error: Assertion Failed: <@ember/component:ember716> had no action handler for: lonerWatch. Initially, they placed the controller in /assets/javascripts/discourse/controllers, but corrected it to /components — though the error persisted. Johani clarified that connector templates and JS files must reside in the same directory (e.g., /connectors/topic-navigation/) and share the same filename, and that the JS should export a plain object with actions, not extend Ember.Controller. After applying these fixes, alangibson confirmed the form now works, noting their main mistake was incorrectly using Ember.Controller.extend where it wasn’t needed. The solution aligns with Discourse’s plugin outlet conventions for Ember 2.10+ as documented here.

I’m trying to create a simple plugin that

  • adds a form above the topic timeline
  • POSTs email address that user enters to a controller

The form is rendered above the timeline, but when I enter an email and click the submit button, I get this error in the browser console:

DEBUG: -------------------------------
vendor.js:49192 DEBUG: Ember  : 3.15.0
vendor.js:49192 DEBUG: jQuery : 3.6.0
vendor.js:49192 DEBUG: -------------------------------
vendor.js:4180 [Violation] 'setTimeout' handler took 489ms
[Violation] Forced reflow while executing JavaScript took 35ms
vendor.js:49192 DEBUG: For more advanced debugging, install the Ember Inspector from https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi
user-presence.js:77 [Violation] 'setInterval' handler took 51ms
vendor.js:49170 Uncaught Error: Assertion Failed: <@ember/component:ember716> had no action handler for: lonerWatch
    at assert (vendor.js:49170)
    at Class.send (vendor.js:44642)
    at Class.superWrapper [as send] (vendor.js:43919)
    at Class.send (plugin-connector.js:75)
    at Class.superWrapper [as send] (vendor.js:43919)
    at vendor.js:22103
    at instrument (vendor.js:50635)
    at vendor.js:22102
    at Backburner._run (vendor.js:67048)
    at Backburner._join (vendor.js:67024)

The (currently incomplete) code is:

/assets/javascripts/discourse/templates/connectors/topic-navigation/loner-watch-topic-form.hbs

<form {{ action 'lonerWatch' content on='submit' }}>    
    <p>Enter your email address to watch this topic for updates</p>
    <input name="email" placeholder="Your email"/>
    <button>Watch</button>
</form>

/assets/javascripts/discourse/controllers/loner-watch-topic-form.js.es6

export default Ember.Controller.extend({
    actions: {
      lonerWatch(content) {
        console.log(content);
      }
    }
  });

/controllers/loners_controller.rb

class LonersController < ApplicationController
   [...]
    # Watch topic as a staged user
    def watch
      user = ensure_user
      topic = Topic.find(params[:topic_id].to_i)
      TopicUser.change(user, topic.id, notification_level: params[:notification_level].to_i)
    end
  end

I’m sure I’m missing something simple here, but I’m just not seeing it. Any help is appreciated.

I just noticed that /assets/javascripts/discourse/controllers should be /assets/javascripts/discourse/components. Unfortunately I still get the same error.

I’m stumped. Does anyone have any ideas what I’m doing wrong here?

The connector template and JS file need to be in the same directory and have the same name. So

/assets/javascripts/discourse/connectors/topic-navigation/loner-watch-topic-form.hbs

<form {{ action 'lonerWatch' content on='submit' }}>    
    <p>Enter your email address to watch this topic for updates</p>
    <input name="email" placeholder="Your email"/>
    <button>Watch</button>
</form>

and

/assets/javascripts/discourse/connectors/topic-navigation/loner-watch-topic-form.js

export default {
  actions: {
    lonerWatch(content) {
      console.log(content);
    },
  },
};

Your action should then work. You can read a bit more here if you’re interested.

Thanks for the reply. It’s working now. It looks like I had several things wrong, but the worst was erroneously using Ember.Controller.extend when it wasn’t needed.