soultrust
soultrust

Reputation: 599

What is the best way for all instances of an Ember component to share a variable?

I have an Ember component which is essentially a panel. There can be multiple instances of this panel on a page, but only one can be "active" at any given time. Each instance of the component must be aware if any of the other panels become "active" so they can remove their "active" state. I would really rather not move the JavaScript to make this happen to a parent component. Instead, I would like to keep it within this component. In Angular, I used to use a static variable to do this. What is best way to do this in Ember?

Upvotes: 1

Views: 430

Answers (2)

Suresh Kumar
Suresh Kumar

Reputation: 74

@arne.b 's anwser sums it pretty well, the best way of handling component's state with common parent data, but if you are dead serious about not using a parent component there is kind of way to get it done.

Example:

import Ember from 'ember';

export default Ember.Component.extend({
   sharedObject: {},
   sharedArray: [],
});

In the above component you can use sharedObject or sharedArray to exchange state with multiple instances of the component. Any changes in the object or array will be reflected to all the instances of the same component.

A sample Ember twiddle.

Upvotes: 0

arne.b
arne.b

Reputation: 4330

I would really rather not move the JavaScript to make this happen to a parent component

Do you want to avoid having the parent component dealing with anything related to panel "activity"? If so, why?* If not:

Ember automatically gives each component's tag (unless it's a tagless component) an id that is accessible from the js code as elementId. You could create a property activePanelId on the parent component and pass it to all panels: {{pa-nel activePanelId=activePanelId}} and then check in each panel

{{#if (eq elementId activePanelId)}}
  {{!whatever is different on the active panel}}
{{/if}}

or use it in the js code:

isActive: Ember.computed('activePanelId', function() {
    return this.get('activePanelId')===this.get('elementId');
},

If the panel becomes active by an action related to itself (e.g. clicking on it), just set activePanelId to the elementId in the respective action - since the property activePanelId exists only once on the parent component, all other panels to which it is passed will take note.

If using the elementId feels to hacky, you might as well give each panel a distinct name and store the activePanelName in the calling component.

*If you really do not want the property in the parent component, you could move it to a service that you then inject into the panel components, but I cannot yet imagine a good reason for preferring that.

Upvotes: 3

Related Questions