这是一个类似于 这一个的问题,但这是针对Ember和Active Model序列化器的最新版本(0.10.2)。
我有一个简单的父母:孩子的关系。
app/models/trail.js
import Ember from 'ember';
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr(),
// relationships
employees: DS.hasMany('employee', { async: true }),
});app/models/employee.js
import DS from 'ember-data';
import Person from '../models/person';
export default Person.extend({
status: DS.attr(),
statusCode: DS.attr(),
});app/models/person.js
import Ember from 'ember';
import DS from 'ember-data';
export default DS.Model.extend({
avatarUrl: DS.attr(),
firstName: DS.attr(),
lastName: DS.attr(),
fullName: Ember.computed('firstName', 'lastName', function() {
return `${this.get('lastName')}, ${this.get('firstName')}`;
}),
});当我创建一个新的Trail并为“hasMany”选择两个雇员时,下面的json 到达服务器(从Rails日志):
{"data":
{"attributes":
{"name":"TEST3",
"gpx-file-url":"a url",
"distance-value":"5"},
"relationships":
{"employees":{"data":[]}}, "type":"trails"}}我的问题是,员工发生了什么事?雇员的id在哪里(他们已经存在于数据库和Ember商店中-也就是说,我并不试图在这个请求中创建子记录)。
编辑
我刚刚发现了这问题,它解释了hasMany关系的id不是由Ember的JSONAPISerializer发送到API的-因为这里的外键实际上必须保存在每个子记录中。因此,从本质上说,通过“选择”员工,你需要保存这样一个事实:他们现在有了父母。因此,所选员工记录需要持久化。
但我的理解是,所有这些都是“开箱即用”的,而Ember会自动发出一个帖子请求来这样做,但情况似乎并非如此。
,这就引出了真正的问题--我如何更新这些孩子?
更新-由于这个问题而增加的赏金已经演变成了。
经过进一步的分析,很明显需要一种新的模式--赋值。所以现在这个问题更复杂了。
现在的模型结构如下:
Trail
hasMany分配
雇员
hasMany分配
赋值
belongsTo小径
belongsTo员工
在我的“新路线”中,我使用奇妙的余烬-功率-选择让用户选择员工。在单击“保存”时,我计划遍历选定的员工,然后创建分配记录(显然,在保存Trail之前或之后,还不确定哪个是最好的)。
然而,的问题仍然是,我不知道如何做到这一点--如何获得“选定的”员工,然后遍历他们来创建任务。
下面是我的模板中相关的EPS用法:
in /app/模板/trails/new.hb
{{#power-select-multiple options=model.currentEmployees
searchPlaceholder="Type a name to search"
searchField="fullName"
selected=staff placeholder="Select team member(s)"
onchange=(route-action 'staffSelected') as |employee|
}}
<block here template to display various employee data, not just 'fullName'/>
{{/power-select-multiple}}(路由-操作是来自船坞的一个助手,它只会自动地将操作发送到我的路由,工作非常好)
这是我的模型:
model: function () {
let myFilter = {};
myFilter.data = { filter: {status: [2,3] } }; // current employees
return Ember.RSVP.hash({
trail: this.store.createRecord('trail'),
currentEmployees: this.store.query('employee', myFilter).then(function(data) {return data}),
});
},
actions: {
staffSelected (employee) {
this.controller.get('staff').pushObject(employee);
console.log(this.controller.get('staff').length);
},
}我直到今天才发现我们仍然需要控制器,所以这可能是我的问题!下面是:
import Ember from 'ember';
export default Ember.Controller.extend({
staff: [] <- I guess this needs to be something more complicated
});这是可行的,我看到一个对象被添加到控制台中的数组中。但是,EPS拒绝工作,因为我在控制台中看到了这个错误:
trekclient.js:91 Uncaught TypeError: Cannot read property 'toString' of undefined(anonymous function) @ trekclient.js:91ComputedPropertyPrototype.get @ vendor.js:29285get @
etc....紧随其后的是:
vendor.js:16695 DEPRECATION: You modified (-join-classes (-normalize-class "concatenatedTriggerClasses" concatenatedTriggerClasses) "ember-view" "ember-basic-dropdown-trigger" (-normalize-class "inPlaceClass" inPlaceClass activeClass=undefined inactiveClass=undefined) (-normalize-class "hPositionClass" hPositionClass activeClass=undefined inactiveClass=undefined) (-normalize-class "vPositionClass" vPositionClass activeClass=undefined inactiveClass=undefined)) twice in a single render. This was unreliable in Ember 1.x and will be removed in Ember 3.0 [deprecation id: ember-views.render-double-modify]因此,我认为这是因为文档中的示例只使用包含字符串的数组,而不是实际的Ember.Objects。但我不知道怎么解决这个问题。
于是,我决定扔掉控制器(哈哈),开始创作。
如果我在Trail模型中添加了一个属性呢?该属性基本上可以是收集所选员工的“虚拟”属性。
in /app/model/trail.js
selectedEmps: DS.hasMany('employee', async {false}) 我将异步设置为false,因为我们不会持久化它们,在保存新的Trail之前,我可以再次将其设置为null。
in /app/模板/trails/new.js
{{#power-select-multiple options=model.currentEmployees
searchPlaceholder="Type a name to search"
searchField="fullName"
selected=model.selectedEmps placeholder="Select team member(s)"
onchange=(action (mut model.selectedEmps)) as |employee|
}}
<block here again/>
{{/power-select-multiple}}这是可行的,它不会在选择第一个员工后“爆炸”。我可以选择多个并从模板中删除它们。该控件似乎运行良好,因为它正在直接突变“model.selectedEmps”。
现在,我认为这是一次黑客攻击,因为我有两个问题:
根本的问题是,我可以接受'mut‘,但仍然有一个问题,当用户点击“保存”,我必须找出哪些员工是被选中的,这样我就可以为他们创建任务。
但我不知道如何访问所选的内容。也许是这种意大利面-怪物-可怕的烂摊子:
save: function (newObj) {
console.log(newObj.get('selectedEmps'));
if (newObj.get('isValid')) {
let emp = this.get('store').createRecord('assignment', {
trail: newObj,
person: newObj.get('selectedEmps')[0]
})
newObj.save().then( function (newTrail) {
emp.save();
//newTrail.get('selectedEmps')
// this.transitionTo('trails');
console.log('DONE');
});
}
else {
alert("Not valid - please provide a name and a GPX file.");
}
},因此,有两个问题需要解决:
newObj.save和each assignment.save会处理这件事的。更新
EPS的开发人员善意地指出,操作处理程序接收到一个数组,因为我更改为使用多个选择,而不是之前的一个选择。因此,该操作正在接收当前所选内容的完整数组。哈!
因此,我能够按如下方式更新操作处理程序,它现在成功地将当前选定的雇员存储在控制器的staff属性中。再近一步。
staffSelected(newList) {
existing.forEach(function(me){
if (!newList.includes(me)) {
existing.removeObject(me); // if I exist but the newList doesn't have me, remove me
}
});
newList.forEach(function(me){
if (!existing.includes(me)) {
existing.pushObject(me); // if I don't exist but the newList has me, add me
}
});
}也许这不是交叉2数组的最佳方式,但这是我在周六晚上4点最不关心的问题。:(
最终问题更新-如何保存数据?
好的,现在我可以获得选定的员工了,我可以创建任务分配,但仍然无法确定Ember需要我如何保存他们,这个保存操作会引发一个错误:
save: function (newObject) {
if (newObject.get('isValid')) {
let theChosenOnes = this.controller.get('theChosenOnes');
let _store = this.get('store');
theChosenOnes.forEach(function (aChosenOne) {
_store.createRecord('assignment', {
trail: newObject,
person: aChosenOne,
});
});
newObject.save().then(function (newTrail) {
newTrail.get('assignments').save().then(function() {
console.log('DONE');
});
});
}
get(...).save is not a function发布于 2016-09-18 12:57:45
最后更新的问题是,在EmberData2.x中,默认情况下关系是异步的,因此从newTrail.get('assignments')返回的不是一个DS.ManyArray,它有一个.save,而是一个PromiseArray,它没有这个特性。
您需要进行一个小的调整才能这样做,因此您可以在已解决的关系上调用.save:
newObject.save().then(function (newTrail) {
newTrail.get('assignments').then(assignments => assignments.save()).then(function() {
console.log('DONE');
});
});https://stackoverflow.com/questions/39506375
复制相似问题