Question

I have a controller for showing item. Users can put the item in their wish list. (Item has many users, User has many Items.)

So, when user enter the webpage, I want to show a AddToList or RemoveFromList button to the user based on isAddedToList property.

Below is the code.

User Model:

var User = DS.Model.extend({
  username: DS.attr('string'),
  email: DS.attr('string'),
  avatar: DS.attr('string'),
  items: DS.hasMany("item", { async: true })
});

export default User;

ItemModel:

var Item = DS.Model.extend({
    name: DS.attr("string"),
    priceInCent: DS.attr("number"),
    salePriceInCent: DS.attr("number"),
    brand: DS.belongsTo("brand"),
    itemImages: DS.hasMany("itemImage", { async: true }),
    users: DS.hasMany("user", { async: true }),
});

export default Item;

ItemRoute:

var ItemRoute = Ember.Route.extend({
  model: function(params) {
    var userId = this.get("session").get("userId");
    return Ember.RSVP.hash({
      item: this.store.find('item', params.item_id),
      user: this.store.find('user', userId),
    });
  },
  setupController: function(controller, model) {
    controller.set('item', model.item);
    controller.set('user', model.user);
  }
});

export default ItemRoute;

ItemController:

var ItemController = Ember.Controller.extend({
  needs: ["current-user", "application"],
  currentUser: Ember.computed.alias("controllers.current-user"),
  isAddedToList: function() {
    var promiseUsers = this.get("item.users"), user = this.get("user");
    return promiseUsers.contains(user);
  }.property("item"),
  actions: {
    addToList: function() {
      var item = this.get("item"), user = this.get("user");
      item.get("users").pushObject(user);
      item.set("addedUserIds", [user.get("id")]);
      item.save();
    },
    removeFromList: function() {
      var item = this.get("item"), user = this.get("user");
      item.get("users").removeObject(user);
      item.set("removedUserIds", [user.get("id")]);
      item.save();
    }
  }
});

export default ItemController;

The problem is when I check the length of promiseUsers with

promiseUsers.get("length")

it always returns 0.

but when I try the same with Chrome console, it returns the length properly. Do I miss something in the route? How to fix the problem?

Était-ce utile?

La solution

The problem is you're using your code synchronously, despite it being an asynchronous property.

The first time you attempt to use an async relationship it will begin resolving the relationship, making a callback to the server is necessary. In your case you try to use the users right away, but they are going to be empty the first time, so you're contains will return false. Since you aren't watching the users' collection it will then update, but the computed property won't update since the computed property was just watching item. This is why when you try it from the console it works, because by the time you attempt to use it in the console it's finished resolving the async collection of users.

isAddedToList: function() {
  var promiseUsers = this.get("item.users"), user = this.get("user");
  return promiseUsers.contains(user);
}.property("user", 'item.users.[]')
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top