1
votes

I am new to Ember, so my approach can be incorrect. I am using latest Ember 2.9.1

My plan is to update route's model and cause all components to render newly added/saved item in a collection.

(I want to update my route's model (userRoles array) with a new record of userRole after I have call save (on createRecord)).

So far I have a route that has a model like this:

model(){
  // this is my "user.edit" route
  let user = this.modelFor('user');
  let newUserRole = this.get('store').createRecord('userRole');
  newUserRole.set('user_id', user.get('id'));

  return RSVP.hash({
    user: user,
    userRoles: store.query('userRole', { user_id: user.get('id') }),
    roles: store.findAll('role'),
    newUserRole: newUserRole
  });
}

I then have a controller and couple of components that modify newUserRole. In a route I have an action for saving new user role:

actions: {
  saveNewUserRole: function () {
    let currentModel = this.modelFor('user.edit');
    currentModel.newUserRole.save().then(function (newUserRole) {
      currentModel.userRoles.addObject(newUserRole);
    });
  }
}

What's interesting is that a new item (newUserRole) gets added to a collection, but in console logging of model tells me that the new object is kind of different from other objects in the collection. Looking through similar issues for ember I find that people use: _internalModel or toArray(): here and here or services (?) for storing/updating data.

(also changed from using pushObject to addObject (v1.3+); plus observers listening for userRoles changes don't get triggered inside of components, or if I call toArray() I get 'Invalid value used as weak map key' error)

Question: What is the correct/Ember way to update my route's model with new item and cause to re-render my template. If I should use services for data, should service keep all items in a toArray() or POJOs?

1

1 Answers

1
votes

ember-data will do most of the ugly relationship work for you automatically.

So for example you should never do something like this:

newUserRole.set('user_id', user.get('id'));

but always this:

newUserRole.set('user', user);

On a .save() ember-data is smart enough to save the id.

Also this looks a bit like you'r trying to load all userRoles for a given user:

store.query('userRole', { user_id: user.get('id') }),

You should only use query when necessary. To fetch a relationship just access the relationship:

user.get('roles'),

Assumed you have roles: hasMany('userRole') in your models/user-role.js.

Next with currentModel.userRoles.addObject you modify a result array of ember data. You should only do this if you want to change the relationship. ember-data will automatically keep your relationships in sync. So after you've set the user on the userRole, the new role will be automatically in the live-array returned by user.get('roles'). So actually you should never modify the array returned by a .query().

So basically this could be your model hook:

// this is my "user.edit" route
let user = this.modelFor('user');
let newUserRole = this.get('store').createRecord('userRole', {
  user
});

return RSVP.hash({
  user,
  userRoles: user.get('roles'),
  roles: store.findAll('role'),
  newUserRole,
});

And this could be your save-action:

actions: {
  saveNewUserRole: function () {
    let currentModel = this.modelFor('user.edit');
    currentModel.newUserRole.save();
  }
}

However if you only want to show the new role after you've saved it you probably should filter on isNew=false when viewing them. User a computer property like userRolesFiltere: Ember.computed.filterBy('model.userRoles', 'isNew', false) or a {{#unless role.isNew}} for that.