Ember,创建用于保存具有多种关系的记录的界面的正确方法

时间:2014-04-21 17:57:45

标签: ember.js ember-data

我有这些模特:

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时创建新的产品记录,并且对于变体也是如此,但是在保存时如何获取所有这些记录并正确设置所有关系字段?

3 个答案:

答案 0 :(得分: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);

但是为了保存模型并将其保存在db中,有一个小问题。按模型保存,因此即使在我们保存商品模型时正确设置了关系,它也不会嵌入与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请求,将内容保存在db中然后使用of pushPayload( http://emberjs.com/api/data/classes/DS.Store.html#method_pushPayload)将所有数据加载回商店。

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

至于观点,我认为你只需要一个产品视图,这就是我的想法:

//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}}

//与productView关联的模板就像

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

答案 1 :(得分:0)

还有另一个我不明白的问题;我使用相同的视图来创建和编辑商品;什么变化只是模型:创建时我使用:

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

编辑时(使用相同模板的另一条路线)我有:

model: function() {
    return this.get('store').find('offer', params.id);
}

它有时只能起作用:对于创建路径,一切正常,但对于编辑路径,它仅在浏览器刷新后才起作用;如果没有(如果来自另一条路线),我得到一个错误,说我正在尝试查找产品但是没有加载记录; 问题是,我可以看到发送的网络请求已经发送,并且收到的答案是所有需要的侧载数据;我也尝试添加:

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

但没有变化;在另一篇文章中我发现我应该用async标记关系:true; 使用它可以工作,但事实是使用async,当来自另一个路由时,Ember数据发送许多产品的http请求,但产品记录已经存在,在模型中侧载(强制由model.refresh重新加载( ));

为什么Ember不能等待model.refresh并从响应中获取记录而不是要求产品记录?

答案 2 :(得分: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});
}