路线的模型钩与灰烬数据“过滤器”不加载相关的计算属性 [英] Route's Model Hook with Ember Data "filter" not loading dependent computed property

查看:90
本文介绍了路线的模型钩与灰烬数据“过滤器”不加载相关的计算属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

希望你能帮助我! :)



我的问题是,我有一个看起来像这样的路由,我期望填充一个项目列表,即只有标记的,请,但不会:

  App.TaggedItemsListRoute = App.ItemsRoute.extend({
model: function(){
var store = this.get(store);
var storePromise = store.find(item,{has_tags:true});
var filtered = store .filter(item,function(item){
return item.get(hasTags);
});
return storePromise.then(function(response){
返回过滤;
});
}
});

现在...只是平淡无常,因为hasTags返回false,因为它依赖于tags返回一个暂时为空的一个ManyArray,它还没有解决(参见下面的模型)。这对我来说似乎很糟糕这是说嘿,我没有在我里面!但我想要说的是请稍后重新计算,过滤器正在寻找一个布尔值,但是我想通过它是嘿,不要解决过滤器,直到所有hasTags已经解决或至少重新计算通过的ManyArray。



如果我只是传回一个承诺作为过滤器的返回值,那么它的作品。 ..()()返回item.get(tags)然后(function(tags){return item.get(hasTags);});



除了它实际上不是,beacuse过滤器得到一个承诺,但它不知道承诺,显然,所以当它寻找一个布尔值,它得到一个承诺,它评估为真,然后几乎显示列表中的所有项目。这不是一个问题,直到我去一个不同的路线,其中有所有的项目,然后回来...而BAM它有所有的项目... hm ....



以下是我暂时得到了...即使它仍然很差,但我可以与...一起生活...

  App.TaggedItemsListRoute = App.ItemsRoute.extend({
model:function(){
var store = this.get(store );
var storePromise = store.find(item,{has_tags:true});
var filtered = store.filter(item,function(item){
var tags = item.get(tags);
如果tags.get(isFulfilled){
return item.get(hasTags);
} else {
return tags.then(function(){
return item.get(hasTags);
});
}
});
return storePromise.then (function(response){
return filtered;
});
}
});

我认为真正的唯一方法是在这个阶段解决这个问题要使用RSVP.all ...任何想法?



实际上,我还没有尝试过我现在可以尝试的一件事是使用setupController进行过滤。唯一的麻烦是,所有的项目将被加载到列表中,然后在大约1秒钟之后视觉上跳回到过滤状态。



模型



我的Ember应用程序(Ember 1.5.1)两个模型(Ember Data beta7):项目和标签。项目有很多标签。

  App.Item = DS.Model.extend({
tags:DS.hasMany(标签,反向:item,async:true),
hasTags:function(){
return!Em.isEmpty(this.get(tags));
}。 property(tags)
});

App.Tag = DS.Model.extend(
item:DS.belongsTo(item,inverse:tags),
hasItem:function(){
return!Em.isEmpty(this.get(item))
} .property(item)
);

如果我将模型更改为以下内容,那么当我去上面的路线,所以它履行承诺。

  App.Item = DS.Model。扩展({
标签:DS.hasMany(tag,inverse:item,async:true),
hasTags:function(){
this.get(tags) 。()函数(标签){
console.log(如果打印标签是loding);
});
return!Em.isEmpty(this.get(标签));
} .property(tags)
});

这是一个脱离的问题,从 Ember Data具有许多异步观察属性简单问题,因为我没有真正解释我的问题,实际上是提出错误的问题。我原来以为我可以修改我的模型hasTags属性在我的路由的上下文中正常运行,但现在我不认为这将正常工作...

解决方案

这似乎是一个非常好的候选人 RSVP.all 。 BTW如果你想要回复RSVP,我在几个星期后就发表了一个谈话(不要太多的关注,比萨饼一半,我饿了, http://www.youtube.com/watch?v=8WXgm4_V85E )。无论如何,您的过滤器显然取决于应该执行的标签收集承诺。因此,在执行过滤器之前等待这些解决方案是适当的。

  App.TaggedItemsListRoute = App.ItemsRoute.extend ({
model:function(){
var store = this.get(store);
return store.find(item,{has_tags:true})then function(items){
var tagPromises = items.getEach('tags');
返回Ember.RSVP.all(tagPromises).then(function(tagCollections){
//在此点所有标签已经收到
//构建你的过滤器,并解决
return store.filter(item,function(item){
return item.get(hasTags) ;
});
});
});
}
});



使用与颜色相似的想法的示例(仅当关系具有3个关联颜色时才显示) / h2>

http://emberjs.jsbin.com / OxIDiVU / 454 / edit



在单独的笔记中,如果你觉得你想要这个钩子立即解决,并填充魔法,你可以欺骗并返回一个数组,然后填充数组一旦结果从服务器回来,让你的应用程序看起来像是反应超快(通过在页面上绘制一些东西,然后神奇的填充,因为结果) / p>

  App.TaggedItemsListRoute = App.ItemsRoute.extend({
model:function(){
var store = this.get(store),
quickResults = [];
store.find(item,{has_tags:true})然后(function(items){
var tagPromises = items.getEach('tags');
返回Ember.RSVP。 all(tagPromises).then(function(tagCollections){
//此时所有标签都已收到
//构建您的过滤器,并解析
return store.filter(item ,function(item){
return item.get(hasTags);
});
});
})然后(function(filterResults){
filterResults.forEach(function(item){
quickResults.pushObject(item);
});
} );

return quickResults;
}
});



快速结果示例立即返回(仅当关系具有3个关联颜色时才显示) / h2>

http://emberjs.jsbin.com / OxIDiVU / 455 / edit


Hopefully you can help me! :)

My issue is that I have a Route that looks like this which I'm expecting to populate a list of items... i.e. "only the tagged ones, please", but it doesn't:

App.TaggedItemsListRoute = App.ItemsRoute.extend({
  model: function() {
    var store = this.get("store");
    var storePromise = store.find("item", { has_tags: true });
    var filtered = store.filter("item", function(item) {
      return item.get("hasTags");
    });
    return storePromise.then(function(response) {
      return filtered;
    });
  }
});

Now... that just plain doesn't work because "hasTags" returns false because it relies on "tags" which returns a ManyArray which is temporarily empty beacuse it hasn't resolved yet (see models below). This seems crappy to me. It's saying "Hey I've gone none in me!" but what I want it to be saying is "please recalculate me later" and the filter is looking for a boolean, but what I want to pass it is "hey, don't resolve the filter until all hasTags have resolved" or at least to recompute the ManyArray that it passes.

If I just pass back a promise as the return value for the filter then it sort of works...

return item.get("tags").then(function(tags){ return item.get("hasTags"); });

Except that it's actually not, beacuse filter is getting a Promise, but it's not aware of promises, apparently, so when it's looking for a boolean it gets a promise which it evaluates as true, and then it pretty much shows all the items in the list. That's not a problem until I go to a different route for items which has, say, all the items on it, then come back... and BAM it's got all the items in it... hm....

The following is how I've "gotten around" it temporarily ... ie it's still buggy, but I can live with it...

App.TaggedItemsListRoute = App.ItemsRoute.extend({
  model: function() {
    var store = this.get("store");
    var storePromise = store.find("item", { has_tags: true });
    var filtered = store.filter("item", function(item) {
      var tags = item.get("tags");
      if tags.get("isFulfilled") {
        return item.get("hasTags");
      } else {
        return tags.then(function() {
          return item.get("hasTags");
        });
      }
    });
    return storePromise.then(function(response) {
      return filtered;
    });
  }
});

I think the only way to really get around this at this stage would be to use RSVP.all... any thoughts?

Actually one thing I haven't tried which I might go try now is to use setupController to do the filtering. The only trouble there would be that ALL the items would get loaded inot the list and then visually "jump back" to a filtered state after about 1 second. Painful!

Models

My Ember App (Ember 1.5.1) has two models (Ember Data beta7): Item and Tag. Item hasMany Tags.

App.Item = DS.Model.extend({
  tags: DS.hasMany("tag", inverse: "item", async: true),
  hasTags: function() {
    return !Em.isEmpty(this.get("tags"));
  }.property("tags")
});

App.Tag = DS.Model.extend(
  item: DS.belongsTo("item", inverse: "tags"),
  hasItem: function() {
    return !Em.isEmpty(this.get("item"))
  }.property("item")
);

If I change the model to the following, it actually does print something to the logs when I go to the route above, so it is fulfilling the promise.

App.Item = DS.Model.extend({
  tags: DS.hasMany("tag", inverse: "item", async: true),
  hasTags: function() {
    this.get("tags").then(function(tags) {
      console.log("The tags are loding if this is printed");
    });
    return !Em.isEmpty(this.get("tags"));
  }.property("tags")
});

This is a spin off question from Ember Data hasMany async observed property "simple" issue because I didn't really explain my quesiton well enough and was actually asking the wrong question. I originally thought I could modify my model "hasTags" property to behave correctly in the context of my Route but I now don't think that will work properly...

解决方案

This seems like a perfectly good candidate for RSVP.all. BTW if you want a rundown on RSVP I gave a talk on it a few weeks back (don't pay too much attention too it, pizza came halfway through and I got hungry, http://www.youtube.com/watch?v=8WXgm4_V85E ). Regardless, your filter obviously depends on the tag collection promises being resolved, before it should be executed. So, it would be appropriate to wait for those to resolve before executing the filter.

App.TaggedItemsListRoute = App.ItemsRoute.extend({
  model: function() {
    var store = this.get("store");
    return store.find("item", { has_tags: true }).then(function(items){
         var tagPromises = items.getEach('tags');
         return Ember.RSVP.all(tagPromises).then(function(tagCollections){
             // at this point all tags have been received
             // build your filter, and resolve that
             return store.filter("item", function(item) {
                return item.get("hasTags");
             });
         });
    });
  }
});

Example using a similar idea with colors (I only show it if the relationship has 3 associated colors)

http://emberjs.jsbin.com/OxIDiVU/454/edit

On a separate note, if you felt like you wanted this hook to resolve immediately, and populate magically after, you could cheat and return an array, then populate the array once the results have come back from the server, allowing your app to seem like it's reacting super quick (by drawing something on the page, then magically filling in as the results come pouring in).

App.TaggedItemsListRoute = App.ItemsRoute.extend({
  model: function() {
    var store = this.get("store"),
        quickResults = [];
    store.find("item", { has_tags: true }).then(function(items){
         var tagPromises = items.getEach('tags');
         return Ember.RSVP.all(tagPromises).then(function(tagCollections){
             // at this point all tags have been received
             // build your filter, and resolve that
             return store.filter("item", function(item) {
                return item.get("hasTags");
             });
         });
    }).then(function(filterResults){
       filterResults.forEach(function(item){
         quickResults.pushObject(item);
       });
    });

    return quickResults;
  }
});

Example of quick results, returns immediately (I only show it if the relationship has 3 associated colors)

http://emberjs.jsbin.com/OxIDiVU/455/edit

这篇关于路线的模型钩与灰烬数据“过滤器”不加载相关的计算属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆