Adding objects to ArrayController, server query is immutable


#1

I’m trying to add objects to my Emberjs Arraycontroller. I have a “create” action that fires when a button is pushed. This works fine but I can’t seem to add the element with the this.pushObject function to the ArrayController. I get this error message:

Uncaught Error: The result of a server query (on App.Software) is immutable.  

I guess this is because I’m using the RESTAdapter to load data and it does not like that I’m adding elements manually?

Here is my controller and the create action.

App.SoftwareIndexController = Ember.ArrayController.extend({
	sortProperties: ['revision'],
	
	create:function(){
        var revision = $('#software_revision').val();
        var doc = $('#software_document').val();

	    var software  = App.Software.createRecord({
	      product_id: 1,
	      revision: revision,
	      doc: doc
	    });
        this.pushObject(software);
	
	}
});

Here is the route

App.SoftwareIndexRoute = Ember.Route.extend({
  setupController:function(controller){
    var product_id = 1;
    controller.set('content', App.Software.find({product_id:1}));
  }
});

Here is the model and store

App.Store = DS.Store.extend({
  revision: 12,
  adapter: 'DS.RESTAdapter'
});

DS.RESTAdapter.configure("plurals", {
  software: "software"
});

App.Software = DS.Model.extend({
  revision: DS.attr('string'),
  doc: DS.attr('string'),
  verified: DS.attr('boolean')
});

And here is the template view with the create form and list of software

<script type="text/x-handlebars" data-template-name="software/index">
  <p>
  <fieldset>
    <legend>Create a new software revision</legend>
    <label for="software_revision">Revision</label>
    <input id="software_revision" name="software_revision" type="text" placeholder="">
    <label for="software_document">Document ID</label>
    <input id="software_document"  name="software_document" type="text" placeholder="">   
    <button class="btn btn-success" {{action create}}>Create</button>
  </fieldset>
  </p>


  {{#if length}}
  <table class="table">
    <thead>
      <tr>
        <th>Revision</th>
        <th>Created</th>
      </tr>
    </thead>
    <tbody>
      {{#each controller}}
          <tr>
            <td>{{revision}}</td>
            <td>{{createdAt}}</td>
          </tr>
      {{/each}} 
    </tbody>
  </table>
  
  {{else}}
  <div class="alert alert-info">
    <button type="button" class="close" data-dismiss="alert">&times;</button>
    <strong>No software revisions found!</strong> start by creating a new revision above.
  </div>
  {{/if}}
</script>

Does anybody know the proper way to add new object to a ArrayController store? Thank you!

This works by the way if I change the route so it doesn’t use the RESTAdapter

App.SoftwareIndexRoute = Ember.Route.extend({
  setupController:function(controller){
    var product_id = 1;
    controller.set('content', []); // not using the RESTAdapter to load data
  }
});

#2

@arnigudj How did you end up working around this?


#3

Ember data has an “all” property for each of your model types so that you can use all the currently loaded models. So for example, if your route looks like:

App.SoftwareIndexRoute = Ember.Route.extend({
  model : function() {
    return App.Software.all();
  }
});

Then, your content array in your SoftwareIndexController will be automatically updated whenever you create or find a new model. Your controller would look like (also, it might be worthwhile to create inputs that bind with your controller in the Template):

App.SoftwareIndexController = Ember.ArrayController.extend({
    sortProperties: ['revision'],

    create:function(){
        var revision = this.get('software_revision');
        var doc = this.get('software_document');

        var software  = App.Software.createRecord({
          product_id: 1,
          revision: revision,
          doc: doc
        });
    }
}