An ember pick list component


#1

I needed a checkbox pick list component and decided to build one myself. I was surprised at how easy it was, and thought I’d post it here to see if anyone had any idea for improvements. The idea is that on your controller you have two collections, one is a list of the available items, the other represents the collection of items that have been picked.

It renders something like this:

{{pick-list items=availableFeatures selected=features}}

component/pick-list.hbs

{{#each pickables}}
   <div class="checkbox">
    <label>
      {{input type="checkbox" name="isAdmin" checked=isPicked}} {{key}}
    </label>
  </div>
{{/each}}

pick_list_component.coffee

App.PickListComponent = Ember.Component.extend
  pickables: (->
    @get('items').map (item) ->
      Ember.Object.create
        key: item
        isPicked: false
  ).property('items')

  picked: Ember.computed.filterBy('pickables', 'isPicked', true)
  keys:   Ember.computed.mapBy('picked', 'key')

  refreshSelected: (->
    keys = @get('keys')
    @set 'selected', keys
  ).observes('keys.@each').on('init')

#2

I hope this code will help you. No need to create a lot of computed properties, because logic of the component looks trivial.

 App.PickListComponent = Ember.Component.extend({
    pickables: function() {
      var selectedItems = this.get('selected');

      return this.get('items').map(function(item) {
          return {
            key: item,
            isPicked: selectedItems.contains(item)
          };
      });
    }.property('items', 'selected')  
})

#3

This is what I have now, it lets you pre-set the selected items (if you had defaults for example).

App.PickListComponent = Ember.Component.extend
  pickables: (->
    selected = @get('selected')
    @get('items').map (item) ->
      Ember.Object.create
        key: item
        isPicked: selected.contains(item)
  ).property('items')

  picked: Ember.computed.filterBy('pickables', 'isPicked', true)
  keys:   Ember.computed.mapBy('picked', 'key')

  onKeysChanged: (->
    keys = @get('keys')
    @set 'selected', keys
  ).observes('keys.@each').on('init')

  onSelectedChanged: (->
    selected = @get('selected')
    pickables = @get('pickables')
    for pickable in pickables
      picked = selected.contains(pickable.get('key'))
      pickable.set('isPicked', picked)
  ).observes('selected').on('init')