简体   繁体   中英

Ember: Update ObjectController property from ArrayController action?

Disclaimer: I'm quite new to Ember. Very open to any advice anyone may have.

I have a action in a ArrayController that should set an ObjectController property. How I can access the right context to set that property when creating a new Object?

Here is abbreviated app code show my most recent attempt:

ChatApp.ConversationsController = Ember.ArrayController.extend({
  itemController: 'conversation',
  actions: {
    openChat: function(user_id, profile_id){
      if(this.existingChat(profile_id)){
        new_chat = this.findBy('profile_id', profile_id).get('firstObject');
      }else{
        new_chat = this.store.createRecord('conversation', {
          profile_id: profile_id,
        });
        new_chat.save();
      }
      var flashTargets = this.filterBy('profile_id', profile_id);
      flashTargets.setEach('isFlashed', true);
    }
  },
  existingChat: function(profile_id){
    return this.filterBy('profile_id', profile_id).get('length') > 0;
  }
});

ChatApp.ConversationController =  Ember.ObjectController.extend({
  isFlashed: false
});

The relevant template code:

{{#each conversation in controller itemController="conversation"}}
  <li {{bind-attr class="conversation.isFlashed:flashed "}}>
    <h3>Profile: {{conversation.profile}} Conversation: {{conversation.id}}</h3>
    other stuff
  </li>
{{/each}}

ArrayController and ItemController are going to be depreciated . As you are new to Ember I think that it would be better for you not to use them and focus on applying to coming changes.

What I can advice you is to create some kind of proxy object that will handle your additional properties (as isFlashed , but also like isChecked or isActive , etc.). This proxy object (actually an array of proxy objects) can look like this (and be a computed property):

proxiedCollection: Ember.computed.map("yourModelArray", function(item) {
  return Object.create({
    content: item,
    isFlashed: false
  });
});

And now, your template can look like:

{{#each conversation in yourModelArray}}
  <li {{bind-attr class="conversation.isFlashed:flashed "}}>
    <h3>Profile: {{conversation.content.profile}} Conversation: {{conversation.content.id}}</h3>
    other stuff
  </li>
{{/each}}

Last, but not least you get rid of ArrayController . However, you would not use filterBy method (as it allows only one-level deep, and you would have the array of proxy objects, that each of them handles some properties you filtered by - eg id). You can still use explicit forEach and provide a function that handles setting:

this.get("proxiedCollection").forEach((function(_this) {
  return function(proxiedItem) {
    if (proxiedItem.get("content.profile_id") === profile_id) {
      return proxiedItem.set("isFlashed", true);
    }
  };
})(this));

I don't see why you need an object that handles setting a property for all the elements in your list. Have each item take care of itself, this means components time.

Controllers and Views will be deprecated anyway, so you would do something like:

App.IndexRoute = Ember.Route.extend({
  model: function() {
    return [...];
  }
});

App.ConversationComponent = Ember.Component.extend({
  isFlashed: false,
  actions: {
    // handle my own events and properties
  }
});

and in your template

{{#each item in model}}
  {{conversation content=item}}
{{/each}}

So, whenever you add an item to the model a new component is created and you avoid having to perform the existingChat logic.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM