Share code between routes


#1

ember-cli: 2.13.2 node: 7.8.0

Hello, I’m a newbie at Ember.

I have a route with this code to set a body class. I will use this code on a couple of routes but not all. I was wondering if it’s possible to share this code between routes?

TIA

-Emmanuel

import Ember from 'ember';

export default Ember.Route.extend({
  activate () {
    Ember.$('body').addClass('loading-authentification');
  },
  deactivate () {
    Ember.$('body').removeClass('loading-authentification');
  }
});

#2

yes, use mixins https://www.emberjs.com/api/ember/2.14.0/classes/Ember.Mixin


#3

Mixins are largely an anti-pattern now. Make sure you understand exactly how Ember’s mixin works and how the order that you mix these mixins actually results in different behavior.

On the larger perspective, it’s always good to know the inner working of Ember’s object model. Namely how all these works: .reopen, .reopenClass, .extend, Ember.mixin (lower case mixin).


#4

Hate to thread jack, but could you point to some resources about this?


#5

Hello, thanks for the answers!

But, I’m really stuck here. Although I googled a lot, read all documentation that I can find, I can’t find a way to do this.

I tried with mixin, reopen and reopenClass.

I think I understand how to create a mixins/reopen/reopenClass but I can’t figure out how to put it in the route under activate/deactivate.

TIA


#6

Ok I’m almost there:

In ./app.js I have set the import of the reopen file:

import SetBodyClass from './custom/css/set_body_class'

In ./custom/css/set_body_class.js I have the following code:

Ember.Route.reopen({                            
  set_body_class(this_class){                   
    console.log (this_class);                   
    alert(this_class);                          
    return Ember.$('body').addClass(this_class);
  }                                             
})

Then in /routes/authentification.js I have this:

import Ember from 'ember';                                      
export default Ember.Route.extend({                             
  activate () {                                                 
   this.set_body_class('red');                                  
  },                                                            
  deactivate () {                                               
   this.set_body_class('blue');                                 
  }                                                             
});

Although console.log() and alert() are working in the route it seems that jQuery is not working and I can’t change the body class of the page.

TIA


#7

Holycow it’s working now! I forgot to change the name of the css class.

routes/authentification.js

import Ember from 'ember';                          
                                                    
export default Ember.Route.extend({                 
  activate () {                                     
   this.set_body_class('loading-authentification'); 
  }                                                 
}); 

./custom/css/set_body_class.js

  Ember.Route.reopen({                            
  set_body_class(this_class){                   
    return Ember.$('body').addClass(this_class);
  }                                             
})

#8

I talked about the issues of Mixins before on this forum. You can see it here

If you’re on Ember Community slack channel, you can do a search on mixin and you’ll get many opinions about it, many are negative.


#9

What would you use the place of the mixin here? A service is the first thing that pops into my mind but that seems overkill for this. You could use an exported class or a simple function either but they don’t feel right compared to the mixin which is built into the framework.


#10

Well, a service is not hooked into the render cycle of the route. OP’s use case is route specific.

It is perfectly ok to encapsulate this in a helper or component. I think component works better because it has a teardown phase.

Just make component that attach class to body on insert, then remove the class on teardown.


#11

Fair point but a component comes with a lot more cognitive overhead than a mixin (not to mention number of files). Most Mixins should only describe a simple self contained behaviour or action but don’t necessarily have lifecycles themselves or work with the DOM. In that case does a mixin or classical inheritance not make more sense than a component?


#12

Rather than using imperative logic to set a body style, you can also add that to the template and use data mapping from a property to set the class. In particular if this is for navigation the link-to can be used to set the style if the url matches the target of the link-to which allows easy management of the navigation links common in web ui and bootstrap in particular.