HaoQi Li
HaoQi Li

Reputation: 12350

Controller computed property is not showing new data additions immediately, where the data is not those returned from the route model

Summary:

Controller computed property issue: In one case, I can see all the things getting added but not see the newly added things immediately (jsbin), and in another case I can see the newly added things immediately but the previously added things don't show up (jsbin).

Second Update of Aug 26:

So I was thinking ... I have these two complementary pieces of code. I just need to combine them and achieve perfection, right? Sadly, it failed miserably, as you can see in this jsbin, nothing shows up at all. :(

This is my failed attempt to combine the two RecordArrays:

officelist: function(){
  var allrecords = [];
  console.log("in oficelist");

  // get the record array that shows previously added records
  var a_recordarray =  App.Office.find({org_id: 'myorgid'});
  a_recordarray.forEach(function(record){
    allrecords.push(record);
  });
  console.log(a_recordarray.toString());
  console.log(allrecords.length);

  // get the record array that shows newly added records
  var b_recordarray = App.Office.filter(function(office) {
        return office.get('org_id') === 'myorgid';
    });
  b_recordarray.forEach(function(record){
    allrecords.push(record);
  });
  console.log(b_recordarray.toString());
  console.log(allrecords.length);

  // return the combination
  return allrecords;

}.property('content.@each')

Details:

I have this simple jsbin app that uses a controller computed property in the code to show a list of names to be displayed. The problem is that whenever a new name is added, you have to refresh the page to see it getting displayed.

You can see its code here.

Controller code with computed property:

officelist: function(){
  return App.Office.find({org_id: 'myorgid'});
}.property('content.@each')

Route returning a different model:

App.OrganizationRoute = Ember.Route.extend({
  model: function() {
    return App.Org.find();
  }
});

Handlebars:

{{#each officelist}}
  <li>{{officename}} </li>
{{/each}}

Constraints: I do need to have the 'org_id' present and I do need to have the route model returning a different model from the model that is displayed.

Update Aug 26: Jonathan has made some progress but please see my comment to his answer as it doesn't solve the problem completely.

Updated Aug 24: Added the complexity that the data to be displayed is different from those returned in the router model. (Also changed ArrayController to ObjectController, but this change has no consequences as ObjectController also has the content property.), below is the old stuff:

Controller code with computed property:

officelist: function(){
  return App.Office.find({org_id: 'myorgid'});
}.property('office.@each')

Handlebars:

{{#each officelist}}
  <li>{{officename}} </li>
{{/each}}

Upvotes: 0

Views: 495

Answers (3)

Jonathan Tran
Jonathan Tran

Reputation: 15276

Change App.OrganizationController's officelist property to this:

officelist: function() {
  return App.Office.filter(function(office) {
    return office.get('org_id') === 'myorgid';
  });
}.property()

The reason is that calling App.Office.find() tries to fetch from the adapter, in your case, localStorage. What you want to do instead is simply pull it out of the store. For this, App.Office.filter() (and in other cases, App.Office.all()) is your friend.

Update:

To also fetch other offices previously saved, fetch them using find(). A place you might do this is when the controller gets initialized in the route's setupController hook.

App.OrganizationRoute = Ember.Route.extend({
  model: function() {
    return App.Org.find();
  },
  setupController: function(controller, model) {
    this._super.apply(this, arguments);
    App.Office.find({org_id: 'myorgid'});
  }
});

You don't need to worry about storing the result because any resulting Office records will be loaded into the store, and your App.Office.all() and App.Office.filter() calls will get the updates automatically.

Upvotes: 1

flynfish
flynfish

Reputation: 5867

If you don't do the find call with the org_id parameter everything works as you want:

officelist: function(){
  return App.Office.find();
}.property('content.@each')

jsbin

Upvotes: 1

Mike Grassotti
Mike Grassotti

Reputation: 19050

The problem is that the computed property is cached and will only refresh when office.@each changes. The office property is not defined on that controller, so office.@each is always null. Probably what you want instead is content.@each. So:

officelist: function(){
  return App.Office.find({org_id: 'myorgid'});
}.property('content.@each')

Now the page will refresh whenever a new office is added.

Upvotes: 1

Related Questions