Javascript Plugins post es6


(Benjamin Kampmann) #1

Following up on the changes for ES6, I noticed my tagger plugin isn’t working anymore.

It boils down to a reference problem with the class.reopen({ statements as the following code:

Discourse.ComposerController.reopen({
	actions: {
		removeTag: function(toRm){
			this.get("content.tags").removeObject(toRm.toString());
		}
	}
,});```

gives me a ```TypeError: Discourse.ComposerController is undefined```.

I saw that @eviltrout moved the ComposerController into the new shiny `.es6` framework but now I am unable to reference and can't really follow how I should be able to. A few additions to also be able to ship `.es6` files in plugins didn't yield any results. Can someone enlighten me how I/we/plugin authors can reference these classes post es6 so I can fix my plugin?

(Benjamin Kampmann) #2

Okay, after reading up on AMD.js (this is what we are using internally, right?) and learning about the injection-model I found a solution to my problem without having to be able to ship .es6 files myself. Using the require() function of AMD, I can do the following instead:

require("discourse/controllers/composer")["default"].reopen({
    actions: {
        removeTag: function(toRm){
            this.get("content.tags").removeObject(toRm.toString());
        }
    },
});

From what I gathered, the “module” you want to pass usually is the filename (without suffix) and ["default'] is needed because one module could export multiple things but this one is only exporting the ComposerController. I am currently doing this right at parsing-time of the JS (could that cause problems?).

I’d still like your feedback about this, whether it is the intended approach/way of doing it or if you know/had a suggestion for a better one.


(Robin Ward) #3

This is not a bad solution but it would be better if you could use .es6 within plugins.

I am surprised actually that adding a .es6 extension in your plugin was not parsed correctly. Just so I’m not crazy, you tried that and the file was not parsed, even after clearing tmp?

Because the better way would be:

import ComposerController from 'discourse/controllers/composer';

ComposerController.reopen({ ... });

(Benjamin Kampmann) #4

So, my investigation showed that first off register_assets for .es6 from plugins isn’t supported in master at the moment. But even adding that, they simply didn’t show up. No messages, no errors, nothing. Just weren’t loaded. Which also mean I might had some syntax errors or something (as I hadn’t figured out the path yet) but it stayed silent. Gonna try again with that approach later and if I can make it work, I’ll send a PR for it :).


(Robin Ward) #5

I’ve just committed a PR that allows the old style of Globals to work with plugins since there isn’t a great upgrade story right away.

With the new PR, all plugins should work as is with ES6 modules with no modifications.

In the future, once more of Discourse is converted to ES6 we will put in proper deprecations and make sure all the major plugins are updated.

https://github.com/discourse/discourse/commit/092f7510b40c2d59bae16ae09f1803e4b9715633


es6 reopening of view+model working only in development?
(Robin Ward) #6

I should add, it’s necessary to rm -rf tmp in development mode to get the latest version of the ES6 stuff working.


(Benjamin Kampmann) #7

Thanks. That looks like a good Balance-Idea. I see if I have time to add .es6-shipping-support to Plugins today.


(Piotr Szal) #8

I need to reopen in my plugin the PreferencesController and it does’t work anymore. The Controller is now in es6 style.

(function() {
window.Discourse.PreferencesController.reopen({});
}).call(this);

Uncaught TypeError: Cannot read property ‘reopen’ of undefined


(Robin Ward) #9

Sorry about that. My backwards compatibility layer had a bug with class names that ended with ‘s’. I’ve just pushed a fix to master so if you check that out, and rm -rf tmp you should be good to go.

I’ll be posting more soon on how to make a plugin fully ES6 compatible, but the effort is not complete so I want people to just use the easy path for now.