How to use a filtered computed property with ember-drag-drop sortable-objects?

Viewed 206

I'm using ember-drag-drop to implement a sortable list. This worked fine until I needed to implement a text filter on the list.

{{#sortable-objects sortableObjectList=filteredItems enableSort=true}}
  {{#each filteredItems as |item index|}}
    {{#draggable-object content=item isSortable=true isDraggable=true}}
      {{item.name}}
    {{/draggable-object}}
  {{/each}}
{{/sortable-objects}}

The filteredItems is a computed property which filters the original list based on a user's text input.

filteredItems: computed('items', 'term', function() {
  let term = this.get('term');
  let items = this.get('items');

  if (term.length > 0) {
    return items.filter(item => item.conditions.some(cond => cond.field.toLowerCase().indexOf(term) > -1 || (cond.term && cond.term.toLowerCase().indexOf(term) > -1)));
  } else {
    return items;
  }
}),

The problem is that a computed can't (normally) be written back to. The actual drag and drop works (the items appear in a different order in the browser), however, the data original order of the items doesn't change.

How can I still allow sorting of the original items data set while still allowing filtering?

1 Answers

Ember's computed properties can also be setted. In your case, you need to define your computed by enabling the set function (from this working twiddle) like this:

filteredItems: Ember.computed('items', 'term', {
    get(key) {
      let term = this.get('term');
      let items = this.get('items');

      if (term && term.length > 0) {
        let filteredItems = items.filter(item => item.name.indexOf(term) > -1);
        return filteredItems;
      } else {
        return items;
      }
    }, 
    set(key, value) {
      let items = this.get('items');
      let filteredItemsCount = 0;
      let newItems = Ember.makeArray();
      items.forEach(function(item, index){
        if(value){
          if(value && value.indexOf(item) > -1){
             newItems[index] = value[filteredItemsCount];
             filteredItemsCount++;
          }
          else{
            newItems[index] = items[index];
          }
        }
        else{
            newItems[index] = items[index];
        }
      });

      this.set('items', newItems);

      return value;
    }
})
Related