Search code examples
jquerybackbone.jsmarionette

Updating multiple models on Backbone.Marionette


Using Marionette and Coffeescript.

I am working on allowing users to check a box on a view's model and then change one attribute on all checked models (like you can do in Gmail, for example).

Right now I am planning on setting the id of the checkbox to the id of the model, and grabbing the ID's of all checked boxes using jQuery and updating one model at a time, perhaps through a function on the collection that receives the array of ID's and the attribute to change.

My question is: is there a particularly neat 'Backbone way' of doing this? Or any suggestions along those lines? Forgive the generality, I am not too good at knowing the backbone way and my google searching did not turn up much.

edit

So I ended up doing it like the following. I also have a selectAll and deselectAll on the view which checks/unchecks all the checkboxes. I didn't update the models to reflect checked or unchecked because it seemed unnecessary since the checked status isn't presisted for any reason and it seems like mass updating models on a selectAll or deselectAll is unnecessary work. And the ID of the checkbox is the ID of the model for that view.

collection:

class MyCollection extends Backbone.Collection
  model: MyModel
....
  batchSave: (ids, attrs) ->
    for id in ids
      @get(id).save attrs, patch: true

in view:

class MyComposite extends Marionette.CompositeView
  events:
    'click .batch-attribute a' : 'attributeSelected'

  prioritySelected: (e) ->
    e.preventDefault()
    ids = $('.edit-select:checked').map( -> @id ).get()
    attr = {attr: e.currentTarget.dataset.value}
    @collection.batchSave ids, attr

Solution

  • Ideally you'll have a collection view and a bunch of item Views as shown below:

    var Checks = Backbone.Collection.extend({});
    var checks = new Checks([{}, {}, {}]);
    var CheckView = Backbone.View.extend({
      initialize: function() {
        this.render();
      },
      events: {
        'click input': 'check'
      },
      render: function() {
        this.$el.append('<input type="checkbox">').appendTo('body');
      },
      check: function(event) {
        this.model.set('selected ', $(event.target).is(':checked'));
      }
    });
    checks.each(function(model) {
      new CheckView({
        model: model
      });
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.2.3/backbone-min.js"></script>

    Each item view is responsible for marking it's model as selected. Later you can simply find the selected models from collection view like this.collection.where({selected:true});