Using Ember Services in Discourse plugins


(David Taylor) #1

I am attempting to make use of Ember “Services” in a discourse plugin. Right now I am just trying to get a simple proof of concept working based off of this tutorial online. Unfortunately I can’t get it working and am not sure if it’s something to do with how plugins are loaded in discourse, or if I’m just doing something wrong. Any help would be appreciated!

Right now the plugin is purely clientside, so the plugin.rb just has basic info.

# name: Test Plugin
# about: A plugin to test Ember services in Discourse
# version: 0.0.1
# authors: David Taylor
// plugins/myplugin/assets/javascripts/discourse/components/comp-test.js.es6
import Ember from 'ember';  
var inject = Ember.inject;

export default Ember.Component.extend({  
    start: inject.service(),
    message: 'test',
    actions: {
        pressMe: function() {
            var testText = this.get('start').thisistest();
            this.set('message',testText);
            console.log(this.get('start').isAuthenticated);
        }
    }
});
// plugins/myplugin/assets/javascripts/discourse/services/start.js.es6
import Ember from 'ember';

export default Ember.Service.extend({  
    isAuthenticated: true,
    thisistest: function() {
        return "hello world";
    }
});
<!-- plugins/myplugin/assets/javascripts/discourse/templates/components/comp-test.hbs -->
<button {{action "pressMe"}}>push me</button><br>  
{{message}}
<!-- plugins/myplugin/assets/javascripts/discourse/templates/connectors/discovery-list-container-top/testfile.hbs -->
<span>Hello World widget here: {{comp-test}}</span>

When the button is clicked, I get an error in the javascript console:
Uncaught TypeError: Cannot read property 'thisistest' of undefined
which I believe just means that the Service hasn’t been loaded/injected properly. I’m unsure of how to go about debugging this further.


Correct way to build components
(Robin Ward) #2

I don’t think we are currently using Ember services so I don’t have a good proof of concept for this.

It could be that our version of Ember doesn’t support them with this syntax?


(David Taylor) #3

Ember 1.13 does support them (I think), the tutorial I linked to says it’s for 1.13.

Maybe you can help me come up with a “Discourse-y” way of doing what I need that doesn’t use services. I’m trying to create a “who’s online” widget which will use the messagebus to be live-updated. I can make an ember “Component” which handles the UI, but I somehow need to get the array of users to be updated whenever a new message is received on the messagebus. Note that the component might be created/destroyed based on the current page that the user is viewing (I think). My plan was to have the singleton service manage the data, and then “bind” it to a field in the component.

I’m very new to Ember so sorry if this is a stupid question!


(Robin Ward) #4

I think the approach you are taking is correct in that case. I can suggest another way to do a singleton but maybe we should try and get this working the ember way?

Actually I looked and we do have a few ember services already! They’re just not used via Ember.inject. The problem is probably that the resolver we use doesn’t resolve them.

I suspect if you add a resolveService method to the custom resolver it might work!

If not, maybe add some debugging to see what Ember.inject is looking up?


(David Taylor) #5

Just gave this a try and it worked first time :slight_smile:

Just added this to the custom resolver:

   resolveService(parsedName) {
      return this.customResolve(parsedName) || this._super(parsedName);
    },

Is there any way for me to add this method from my plugin? Or if not is a pull request to the main discourse repo likely to be accepted?


(Robin Ward) #6

It should definitely be a pull request to master to add this. I can see many people wanting to add services the idiomatic way!


(David Taylor) #7

Ok, hopefully I’ve done that correctly - let me know if not! :slight_smile: