es6 reopening of view+model working only in development?


(Joe Seyfried) #1

I am currently struggling with something very weird (wasn’t sure if it’s related to this topic, so I opened a new one): I want to modify the footer buttons for specific topics. Therefore, I put this code into the assets/javascript/discourse/views directory, file topic-footer-buttons.js.es6:

export default Discourse.TopicFooterButtonsView.reopen({
  // Add the buttons below a topic
  createButtons: function() {
    var topic = this.get('topic');

The very, very weird thing is: this works on my development install under Mac OS X; but not on my production system. On the latter, this file gets chewed up into the compressed js files, but is actually never called - I tried to alert() from several places (even before the reopen call), but the code never gets touched.

Is there something fundamentally wrong with this approach? Looking around, I mainly found extend(), but not reopen() in the es6 files for models or views (I have the very same problem with a reopened model es6, too) - do I have to reopen from the initialize function of the default object?

Moving the discourse search box and making it functional - how?
(Robin Ward) #2

If you need to reopen a class from a plugin to add to it you should do it in an initializer. Otherwise you’re not sure if it’s been loaded or not!

Take a look at how the tagging plugin does it:

(Joe Seyfried) #3

Great, makes sense (also that things are possibly in another order in development mode)… Thanks a lot.

One more question on this, though: can you extend() that way although you cannot reopen()?

Hm… I changed my code to reopen() in the initialize function. Now, I’m back to square zero: it doesn’t even fire in development mode. The export default is executed on load, but the code inside gets never executed! Is there something to beware of with the name property? Should that be the name of the overwritten class, or something special?

(Robin Ward) #4

Yes, extend() makes a new class and you can do that in its own file. You must import what you are extending, and it should all work.

(Joe Seyfried) #5

Oops, my edit and your reply were (almost) simultaneous… sry. Can you take a look at my new problem above?

(Robin Ward) #6

The name should be something unique like ‘extends-blah-blah’ - all initializers should be automatically run if present in that initializers folder with the es6 extension.

(Joe Seyfried) #7

Oh dammit - just too many ways to get confused. :confused: Thanks. So to reopen() a view, you must place the code inside the initializers folder, not in the views folder. If you extend(), you don’t need to do it via initialize(), so you can put it into views…

(Robin Ward) #8

Right, an initializer needs to be in the initializers folder, a view class needs to be in the view folder.

The distinction is extend makes a whole new thing. People need to be able to include that thing as views/thing. The initializer reopens an existing thing to add new methods to it.

(Joe Seyfried) #9

Hm… now, I try to wrap my brains around a new complication: say I want re reopen discourse/models/composer. Since this is .js and not .js.es6, I fail at the very first line:

import Composer from 'discourse/models/composer';

…the only thing I can do is import the composer view - but the following code fails in the init method if I reopen the view and try to access the model in order to customize it (is it too early to ask the view for its model?):


(Robin Ward) #10

Models are unfortunately the trickiest to reopen since they haven’t been migrated to ES6 (they are the last major part – I have set up the base for doing it but have to put in the time.)

To reopen the composer model, instead of importing it just do Discourse.Composer.reopen in the initializer. Unfortunately this will break once we move to ES6, although there will be a compatibility layer like we have for views and controllers so you’ll have some time to update it once those models are ES6ified.

(Joe Seyfried) #11

Great, works like a charm. For now. :wink: Thanks!