jeudi 8 octobre 2015

Track selections in an EmberJS table component across routes

I have a table-based component and a service to track selections. The service manages an Ember.Map where the key is the table id, and the value an array of ids that represent selected rows.

The reason for using a service to track selections is that I want to maintain the selections even when the route changes. The service looks like this:

import Ember from 'ember';

export default Ember.Service.extend({
    selections: null,
    init() {
        this._super();
        this.set('selections', Ember.Map.create());
    },
    add(tableId, rowId) {
        console.log("add selection");
        var selections = this.get('selections');
        if (selections.get(tableId) === undefined) {
            selections.set(tableId, Ember.A([]));
        }
        selections.get(tableId).pushObject(rowId);
        console.log(selections.get(tableId));
    },
    remove(tableId, rowId) {
        console.log("remove selection");
        var selections = this.get('selections');
        if (selections.get(tableId) === undefined) {
            return;
        }
        selections.get(tableId).removeObject(rowId);
        console.log(selections.get(tableId));
    },
    isSelected(tableId, rowId) {
        console.log("isSelected");
        var selections = this.get('selections');
        if (selections.get(tableId) === undefined) {
            return;
        }
        var index = selections.get(tableId).indexOf(rowId);
        if (index === -1) {
            return false;
        } else {
            return true;
        }
    },
});

I can get the service to track the selections fine, but have the following two problems:

  1. I'm unable to get the template to show an "X items selected" message; and 2. when the route changes, I'm unable to reselect the checkboxes that are supposed to be selected.

What I've tried

Display the number of items selected

In the book-table component I've created an Ember.computed.alias to the selections map on the service, and created a computed property on that to return the selected rows for the given table.

import Ember from 'ember';

var BookTable = Ember.Component.extend({
    tableSelections: Ember.inject.service('table-selections'),
    selections: Ember.computed.alias('tableSelections.selections'),
    selectedBooks: Ember.computed('selections', function() {
        var author = this.get('author');
        return this.get('selections').get(author.id);
    }),
    actions: {
        change(bookId) {
            var author = this.get('author');
            var tableSelections = this.get('tableSelections');
            if (tableSelections.isSelected(author.id, bookId)) {
                tableSelections.remove(author.id, bookId);
            } else {
                tableSelections.add(author.id, bookId);
            }
        }
    },
});

BookTable.reopenClass({
    positionalParams: ['author', 'books'],
});

export default BookTable;

In the template, I then use {{selectedBooks.length}}; however, this displays nothing.

Rechecking checkboxes

I tried to wire up the checkbox's checked attribute to a computed property on the component, but is always returned true. Sadly I've lost the code for this.


So how can I update the template when the selections change or restore selections when changing route?

The full code can be found at GitHub in the jonblack/ember-model-based-sidebars repository in the book-table-component-service branch.

Aucun commentaire:

Enregistrer un commentaire