Make clicked button look active, other buttons should look inactive


#1

Hi everyone,

So I have a group of buttons and each button is its own component. When I click on a button component, I set its ‘isActive’ property to true, which will add a class to distinguish it from unclicked button components. But when I click on another button component, I want to set 'isActive` to false on the previous clicked button component so that only one button component ever looks like it’s toggled active. How would I do this the Ember way? Is it not a good idea to make each button its own component?

Here is a link to a simple twiddle example: https://ember-twiddle.com/e06d287600d72c123a34df81bf3afd16?numColumns=2&openFiles=styles.app.css%2Cstyles.app.css

Let me know if I can do anything else to help you help me, thanks.


Making clicked button look active and other inactive
#2

I’ve created a new twiddle that adapts the one you created to demonstrate one way of doing what you’re asking. Since all the buttons have a shared state that drives their active appearance I’ve set up a parent component called filter-selector that handles the shared state between all the buttons.

This solution is following the data-down actions-up pattern that is the preferred method for handling state changes among components. Values for tag and activeTag are handed down to each button. The action setTagActive is called by a button when clicked, sending its tag text up to the filter-selector. The action changes the value of activeTag in the filter-selector. That change in the activeTag property flows down through each filter-tag-btn template causing each button to re-evaluate whether its tag matches the active tag and therefore if it should display the active state.

The highlights of the code are shown here for a quick look without going to the twiddle…

// filter-selector.js
import Ember from 'ember';
export default Ember.Component.extend({
  tags: null,
  activeTag: null,
  actions: {
    setTagActive(tag) {
      this.set('activeTag', tag)
    }
  }
});

// filter-selector.hbs
{{#each tags as |tag|}}
	{{filter-tag-btn tag=tag activeTag=activeTag setTagActive=(action 'setTagActive')}}
{{/each}}
// filter-tag-btn.js
import Ember from 'ember';
export default Ember.Component.extend({
  tagName: 'button',
  classNameBindings: ['isActive:is-active'],

  tag: null,
  activeTag: null,
  isActive: Ember.computed('tag', 'activeTag', function() {
    return this.get('tag') === this.get('activeTag')
  }),
  click() {
    this.setTagActive(this.get('tag'))
  }
});

#4

I hope this thread is still active. I’m thinking of creating a new topic but will try to communicate here first.

I’m new to ember and basically i’m trying to achieve the same OP’s goal: making clicked button active and other buttons look inactive. But this time the group of buttons are in a single component.

I made everything work fine. My question is: are there any problems with my implementation? or is there an easier way to do this.

Any advice would be greatly appreciated. Hoping someday to contribute to emberjs as well.