2014-04-21 29 views
1

我有这些模型:灰烬,保存记录用的hasMany关系创建界面右边的方式

Gmcontrolpanel.Offer = DS.Model.extend({ 
    name: DS.attr('string'), 
    date: DS.attr('string'), 
    duration: DS.attr('number'), 

    products: DS.hasMany('product', {async: true}), 
}); 

Gmcontrolpanel.Product = DS.Model.extend({ 
    name: DS.attr('string'), 
    description: DS.attr('string'), 

    offer: DS.belongsTo('offer'), 
    variations: DS.hasMany('variation', {async: true}) 
}); 

Gmcontrolpanel.Variation = DS.Model.extend({ 
    description: DS.attr('string'), 
    quantity: DS.attr('number'), 
    price: DS.attr('string'), 

    product: DS.belongsTo('product') 
}); 

我试图建立一个可重复使用的界面,用于创建/编辑的要约;我为插入产品和插入变体提出了两个单独的视图;

该产品视图有一个+和一个 - 按钮来添加或删除产品,以及相同的变异视图;

路由的型号是:

model: function() { 
    return this.get('store').createRecord('offer'); 
} 

我想的是,在点击保存按钮时,所有(报价,产品和变种)被保存;

首先:哪一个是最好的实现方式? containerViews? collectionViews或{{#each}}循环?

然后,如何创建子记录并将它们绑定到子视图上的输入字段?我的意思是:每次插入productView时,我都可以创建新的产品记录,并且变体的内容相同,但在保存时如何获取所有这些记录并正确设置所有关系字段?

回答

1

下面是如何建立的关系的骨架例如:

var newOffer= store.createRecord('offer', {name:....}); 
//or you can do newOffer.set('name',...); 

var newVariation = store.createRecord('variation', {description:.....}); 

var newProduct = store.createRecord('product', {name:..., description:.....}); 

newProduct.get('variations').pushObject(newVariation); 

newOffer.get('products').pushObject(newProduct); 

但保存模型和数据库坚持它,有一个小问题。保存是按照每个模型进行的,因此,即使您在保存商品模型时正确设置了关系,它也不会嵌入与hasMany关系模型关联的数据。所以我们可以这样做:

注意:我已经阅读了关于批量保存的内容,但还没有尝试过 - 你可能想要尝试一下,但如果没有效果,那么我会保存每个模型自下而上像

newVariation.save().then(function(){ 
    newProduct.get('variations').pushObject(newVariation); 
    //since the variation model is already saved, it has id associated with the model 
    //so ember data now knows that it should set variations as variations:[id of the variation model we just saved] when sending post request for product 
    newProduct.save().then{ //same pattern as above } 
}, function(){//handle failure} 

这里的情况很简单,我们只有一个变体和一个产品,但你可能有多个。我们可以做rsvp.all同步保存的承诺,但它有点呆滞,因为你必须为每次保存进行单独的API调用,并且因为你可能有多种变体和产品,所以没有ajax调用可能有点疯狂。解决这个问题的一种方法是通过循环遍历模型来创建自己的json结构,并将这些模型组合成单个json,并使用jQuery ajax api调用发出单个post请求,将内容保存到数据库中,然后使用pushPayload( http://emberjs.com/api/data/classes/DS.Store.html#method_pushPayload)将所有数据加载回商店。

这就是我在类似情况下所做的,但可能有更多优雅的解决方案,所以我会等待更多的意见。

至于视图的事情,我想你需要的只是产品的图,这就是即时通讯思想:

利用ProductView相关
//offer.hbs 
Bunch of form elemnts to update name description 
+ - buttons to add product 
{{#each product}} 
    {{#view productView product=this}}//this is just a normal view 
{{/each}} 

//你的模板会像

+ - buttons to add variations to product 
{{#each product.variations}} 
    Show form elments to update name and description 
{{/each}} 
+0

好的,谢谢你的这个;它在帮助;这个观点如何:你认为在这种情况下最好的是什么?我的意思是,因为需要在主视图中显示许多产品视图,并且在任何产品视图中显示许多变体视图,所以最佳选择是什么?将它们推入containerViews(一个在主视图中,一个在每个productsView中);或者将它们推入collectionViews(容器和collectionview之间的区别是什么?)或其他东西... –

+0

我已经更新了关于我认为会视图的用法的答案。我没有使用过collectionView,但是使用了containerView,而collectionView似乎可以扩展容器视图,但是在你的情况下,普通视图应该足够了。 –

+0

谢谢你的帮助,我已经接受你的答案,因为它正在把我推向正确的方向;特别是将儿童记录推入父母关系的方式是我在文档中找不到的一步... –

0

还有另一个我不明白的问题;我使用相同的观点来创建和编辑报价;什么样的变化仅仅是模式:创建当我使用:

model: function() { 
    return this.get('store').createRecord('offer'); 
} 
编辑(使用另一条路线相同的模板)我有当

​​

它的工作原理只是偶尔:为创建路线一切正常,但对于编辑路线,它只在浏览器刷新后才起作用;如果不是(如果来自另一条路线),我收到一个错误,说我试图查找产品,但记录没有加载; 问题是我可以看到提供的网络请求已发送,并且接收到所有需要的侧装数据的答案;我也试着补充:

setupController: function() { 
    model.refresh(); 
} 

但没有什么变化;在另一篇文章中,我发现我应该用async标记关系:true; 与此它工作,但事情是使用异步,当来自另一条路线时,Ember数据发送许多http请求为产品,但产品记录已经存在,sideloaded在模型中(被强迫由model.refresh重新加载());

为什么Ember无法等待model.refresh并从响应中取出记录而不是询问产品记录?

+0

这听起来像你不能正确加载嵌套的数据,看看这篇文章是关于如何我们可以加载嵌套数据http://stackoverflow.com/questions/19244014/ember-data-nested-models/19345990#19345990。当我不想要异步加载时,我已经写下了json结构应该如何。此外,您可能不想在setupController上执行刷新,因为setupController已获取控制器和模型http://emberjs.com/guides/routing/setting-up-a-controller/。 –

+0

是的,服务器已经以正确的方式发送嵌套数据;问题是只有当你来自/提供路线(即提供名称列表)时,它才会执行模型挂钩;在该路由嵌套记录不加载(这是有意避免加载产品带宽浪费,这里不需要)...然后,过渡到/ offer /:id以查看要约的细节,它需要加载嵌套的记录;如果它会在这里执行模型钩子,则问题将得到解决,因为单个商品的模型会正确加载嵌套记录... –

+0

如何转换为offer /:id路由。无论是使用link-to还是transitionTo,在这两种情况下,您都需要传递模型,因此模型挂钩会在您的路由中转义。它只有当你想直接去提供/:id路由(通过url直接)你会打到模型钩 –

0

怎么样,如果我们给这setupController

setupController:function(controller, model){ 
    model.reload().then(function(data){controller.set('model', data);}); 
} 

或者,如果你所创造的一个动作过渡到编辑模式,并在行动,你先和内重新加载模型一试其再勾,你使用重新加载的模型数据执行transitionToRoute。例如:

goToEdit: function(model){ 
    model.reload().then(function(data){transitionToRoute('offer.edit', data}); 
} 
+0

这会在加载路由时给出错误;可能是因为,与执行模型钩子时发生的不同,setupController钩子不会停止执行下面的代码,或者执行得太晚......在任何情况下,我都可以看到视图中的代码在模型重新加载之前执行当尝试访问模型时,它会导致错误 –