Data: pushing raw JS objects to RecordArray

Created on 11 Jun 2015  路  15Comments  路  Source: emberjs/data

19+ no longer supports the pushObject method to add native JS objects to RecordArrays.
See JS Bin for use case that worked in previous releases. Documentation for MutableArray.pushObject seems to indicate this should be supported.
http://emberjs.jsbin.com/gijero/1/edit?html,js,console,output

Most helpful comment

@chrismllr Sorry for the late response, but you could return a copy of the array in your model hook:

export default Ember.Route.extend({
  model: function () {
    return this.store.findAll('post').then(posts => posts.toArray());
  }
});

All 15 comments

seeing this also in the upgrade

It's not only pushObject but also unshiftObject and their +s versions. It used to be useful for adding created records into already fetched array.

// pseudo-code
var array = store.find('user', params);
var user = store.createRecord('user');
array.pushObject(user); // TypeError: internalModel.getRecord is not a function
array.pushObject(user._internalModel); // 'works'

@gregwallan

Hi, I have same problem too , Do you find any way to solve this problem?

isn't the result of store.find('user', params) supposed to be readOnly?

yes it no longer works in 19+ and it is intentional as it was working in the past but it was private

a new solution like this seems to work without having to use private apis

var self = this;
var usersArray = [];
store.find('user', params).then(function(users){
  usersArray.addObjects(users);
  usersArray.addObject(self.store.createRecord('user' ));
}

How do you change the order of objects in a record array now?

Is there a way to convert a RecordArray to a 'normal' Ember Array? I have a large project that pushes many objects to RecordArrays. Now I have to convert everything.

Not being able to push to a RecordArray adds a lot of unnecessary code. I have difficulty trying to understand this change.

Edit: wow, even getObjectAt doesn't seem to work properly anymore. Fuuu...

recordArray.toArray() should work
@dschmidt you can still reorder records fine, just can't push arbitrary objects.
@Baukereg objectAt works

@Baukereg please comment with any use cases which are hard now, I am sure most of them are pretty simple to implement

@igorT maybe you can shed some light on this one...

In the model hook on page load, I store.find orders and reports for a graph. I then set a long poll to occur every 10 seconds to fetch the orders and reports from the last 10 seconds. I then push them into the arrays of my initial store.find.. Here is my code

  pollReports() {
    const from = moment().subtract(10, 's').toJSON();
    this.controller.setProperties({
      currentPollDateFrom: from,
      currentPollDateTo: moment().toJSON()
    });

    Ember.RSVP.hash({       
       reports: this.store.query('report', {
        dateFrom: from,
        dateTo: moment().toJSON(),
        range: 'interval',
        search: this.controller.get('search') || '*'
      }),
      orders: this.store.query('order', {
        dateFrom: from,
        dateTo: moment().toJSON(),
        search: this.controller.get('search') || '*'
      })
    })
    .then(resp => {
      const reports = this.get('currentModel.reports');
      const orders = this.get('currentModel.orders');

      resp.reports.forEach(r => reports.pushObject(r));
      resp.orders.forEach(o => orders.unshiftObject(o));

      this.controller.send('unloadReports');
    })
    .catch(reason => Ember.Logger.error('failed to poll for reports & orders', reason))
    .finally(() => this.set('currentPoll', later(this, this._pollReports, 10000)));
  }

@Keeo you just saved my life with your code... ._internalModel was what I was looking for! Thank you!

@williamweckl _internalModel is a _private_ API and likely to break without warning in future releases of Ember Data. If you need to rearrange the order you should copy it with toArray.

@chrismllr Sorry for the late response, but you could return a copy of the array in your model hook:

export default Ember.Route.extend({
  model: function () {
    return this.store.findAll('post').then(posts => posts.toArray());
  }
});

@fivetanley thank you for the late response, was pretty timely for me.

I'm dealing with a situation where I cannot use .toArray() since it breaks other functionalities (I'm trying to use ember-selectize while enabling adding new items). Here is my item adding action:

newItem(label) {
  const item = this.store.createRecord("item", { label }); // it's the same if I use a POJO

  this.currentModel.items.pushObject(item);                // breaks with aforementioned error
  this.currentModel.items.pushObject(item._internalModel); // no error, but doesn't work either
}

Any clue on what I can do here?
Thanks!

Was this page helpful?
0 / 5 - 0 ratings