Это аналогичный вопрос this one, за исключением того, что это касается последних версий Ember и Сериализаторы активной модели (0.10.2).EmberJS 2.7 = has_many конфигурация для сериализаторов Ember-Data и Active Model, используя Ember-Power-Select (и загруженные боковые, а не встроенные данные)
У меня есть простой родитель: детские отношения.
приложение/модель/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 }),
});
приложения/модель/employee.js
import DS from 'ember-data';
import Person from '../models/person';
export default Person.extend({
status: DS.attr(),
statusCode: DS.attr(),
});
приложения/модель/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')}`;
}),
});
Когда я создаю новый трейл и выберите двух сотрудников для «hasMany», следующий json приходит сервер (из журнал Rails):
{"data":
{"attributes":
{"name":"TEST3",
"gpx-file-url":"a url",
"distance-value":"5"},
"relationships":
{"employees":{"data":[]}}, "type":"trails"}}
Вопрос в том, что случилось с сотрудниками? Где идентификаторы сотрудников (они уже существуют как в базе данных, так и в Ember Store - т.е. я не пытаюсь создавать дочерние записи в этом запросе).
EDIT
Я только что нашел this вопрос, который объясняет, что идентификаторы для отношений hasMany не отправляются JSONAPISerializer Эмбера к API - так как внешний ключ здесь на самом деле должен быть сохранен в каждой детской записи , Поэтому, по сути, «отбирая» сотрудников, вам нужно сохранить тот факт, что теперь у них есть родитель. Таким образом, выбранные записи сотрудников должны быть сохранены.
Но я понял, что все это работает «из коробки», и что Эмбер автоматически запускает запрос POST для этого, но это, похоже, не так.
В этом случае возникает вопрос: как мне обновить эти дети?
ОБНОВЛЕНИЕ - BOUNTY ДОБАВЛЕН КАК ОНА ЭТОТ ВОПРОС эволюционировал
После дальнейшего анализа, выяснилось, что требуется новая модель - назначения. Теперь проблема сложнее.
структура модели теперь это:
Trail
hasMany назначения
Сотрудник
hasMany заданий
Назначение
belongsTo Trail
belongsTo Сотрудник
В моем 'новом пути' маршрут, я использую фантастический ember-power-select, чтобы позволить пользователю выбрать сотрудник. При нажатии «Сохранить» я планирую итерацию по выбранным сотрудникам, а затем создаю записи присваивания (и, очевидно, сохраняю их до или после сохранения самого трейла, не уверен, что это еще лучше).
Проблема все еще в том, что я не знаю, как это сделать - как добраться до «избранных» сотрудников, а затем перебирать их для создания заданий.
Итак, вот соответствующее использование EPS в моем шаблоне:
в /app/templates/trails/new.hbs
{{#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? Это свойство может в основном быть «фиктивным» свойством, которое собирало выбранных сотрудников.
в /app/models/trail.js
selectedEmps: DS.hasMany('employee', async {false})
Я установил асинхра ложь, так как мы не будем сохраняться их и перед сохранением нового Trail я могу просто установить это снова нуль.
в /app/templates/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» к действию, так что я могу добавить дополнительную логику, я не могу понять, как чтобы получить доступ к тому, что на самом деле хранятся в Собствености «model.selectedEmps»
- Даже если я могу понять (1) Я должен всегда убедиться, что «selectedEmps» опустошается при выходе из этого маршрута, в противном случае следующих время, в которое вводится этот маршрут, он будет помнить, что было , выбранное ранее (так как они сейчас в магазине Ember.Store)
Основная проблема заключается в том, что я могу жить с помощью «мута», но все же имею проблему, когда пользователь нажимает «Сохранить». Я должен выяснить, какие сотрудники были выбраны, поэтому я могу создайте для них задания.
Но я не могу понять, как получить доступ к выбранному. Может быть, что-то это спагетти-монстр-ужасный беспорядок:
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.");
}
},
Таким образом, есть две проблемы решить:
- Как получить выбранные сотрудники, итерацию и создавать задания.
- Как сохранить результаты в API (JSON-API с использованием Rails). I предположим, что
newObj.save
иeach assignment.save
позаботятся об этом .
UPDATE
Разработчик EPS любезно указал, что обработчик действия получает массив, так как я изменил с помощью множественного выбора, ни одного выбора, как это было раньше. Таким образом, действие получает полный массив того, что в настоящее время выбрано. DOH!
Таким образом, я смог обновить обработчик действий следующим образом, который теперь успешно сохраняет выбранных сотрудников в свойстве персонала контроллера. На один шаг ближе.
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 утра в субботу вечером.:(
FINAL ПРОБЛЕМА UPDATE - как сохранить данные
Итак, теперь, когда я могу получить выбранные сотрудников, я могу создавать задания, но до сих пор не могу понять? то, что 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
ли 'employee' модели имеет' belongsTo' отношения с 'trail'? Если это так, я считаю, что запись только хранится в стороне 'ownTo' по умолчанию, поскольку это норма, когда дело касается ORM. – rmmmp
Нет, нет определенного определения. Должен ли я добавить это? – rmcsharry
@MikkoPaderes Я добавил 'ownTo', и это приводит к тому, что массив отношений сотрудников удаляется из json, отправляемого в api. Это имеет смысл, поскольку вы обычно не ожидали, что «trail» создаст конечную точку для получения этого массива и обновит внешние ключи всех этих сотрудников. Хотя я могу представить сценарии, где вы можете этого захотеть. – rmcsharry