首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >EmberJS 2.7 = embedded和活动模型序列化器的has_many配置,使用Ember-Power-Select (和侧加载,而不是嵌入式数据)

EmberJS 2.7 = embedded和活动模型序列化器的has_many配置,使用Ember-Power-Select (和侧加载,而不是嵌入式数据)
EN

Stack Overflow用户
提问于 2016-09-15 08:27:09
回答 1查看 393关注 0票数 0

这是一个类似于 这一个的问题,但这是针对Ember和Active Model序列化器的最新版本(0.10.2)。

我有一个简单的父母:孩子的关系。

app/models/trail.js

代码语言:javascript
复制
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

代码语言:javascript
复制
import DS from 'ember-data';

import Person from '../models/person';

export default Person.extend({
  status: DS.attr(),
  statusCode: DS.attr(),
});

app/models/person.js

代码语言:javascript
复制
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日志):

代码语言:javascript
复制
{"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

代码语言:javascript
复制
  {{#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}}

(路由-操作是来自船坞的一个助手,它只会自动地将操作发送到我的路由,工作非常好)

这是我的模型:

代码语言:javascript
复制
  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);
    },
  }

我直到今天才发现我们仍然需要控制器,所以这可能是我的问题!下面是:

代码语言:javascript
复制
import Ember from 'ember';

export default Ember.Controller.extend({
  staff: [] <- I guess this needs to be something more complicated
});

这是可行的,我看到一个对象被添加到控制台中的数组中。但是,EPS拒绝工作,因为我在控制台中看到了这个错误:

代码语言:javascript
复制
trekclient.js:91 Uncaught TypeError: Cannot read property 'toString' of undefined(anonymous function) @ trekclient.js:91ComputedPropertyPrototype.get @ vendor.js:29285get @ 

etc....

紧随其后的是:

代码语言:javascript
复制
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

代码语言:javascript
复制
selectedEmps: DS.hasMany('employee', async {false}) 

我将异步设置为false,因为我们不会持久化它们,在保存新的Trail之前,我可以再次将其设置为null。

in /app/模板/trails/new.js

代码语言:javascript
复制
  {{#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”。

现在,我认为这是一次黑客攻击,因为我有两个问题:

  1. 如果我将'mut‘更改为一个操作,这样就可以添加进一步的逻辑,我就无法理解如何访问属性'model.selectedEmps’中实际存储的内容。
  2. 即使我能计算出(1)我必须始终确保离开这个路由时'selectedEmps‘是空的,否则下次输入这个路由时,它会记住以前选择的内容(因为它们现在在Ember.Store中)。

根本的问题是,我可以接受'mut‘,但仍然有一个问题,当用户点击“保存”,我必须找出哪些员工是被选中的,这样我就可以为他们创建任务。

但我不知道如何访问所选的内容。也许是这种意大利面-怪物-可怕的烂摊子:

代码语言:javascript
复制
    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.");
      }
    },

因此,有两个问题需要解决:

  1. 如何获得选定的员工,迭代和创建外派。
  2. 然后如何将结果保存到API (使用Rails的JSON)。我想newObj.saveeach assignment.save会处理这件事的。

更新

EPS的开发人员善意地指出,操作处理程序接收到一个数组,因为我更改为使用多个选择,而不是之前的一个选择。因此,该操作正在接收当前所选内容的完整数组。哈!

因此,我能够按如下方式更新操作处理程序,它现在成功地将当前选定的雇员存储在控制器的staff属性中。再近一步。

代码语言:javascript
复制
  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需要我如何保存他们,这个保存操作会引发一个错误:

代码语言:javascript
复制
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
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-09-18 12:57:45

最后更新的问题是,在EmberData2.x中,默认情况下关系是异步的,因此从newTrail.get('assignments')返回的不是一个DS.ManyArray,它有一个.save,而是一个PromiseArray,它没有这个特性。

您需要进行一个小的调整才能这样做,因此您可以在已解决的关系上调用.save

代码语言:javascript
复制
newObject.save().then(function (newTrail) {
    newTrail.get('assignments').then(assignments => assignments.save()).then(function() {
        console.log('DONE');
    });
});
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39506375

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档