2016-09-15 5 views
0

Это аналогичный вопрос 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».

Теперь, я думаю, что это хак, потому что у меня есть две проблемы, связанные с ним:

  1. Если я изменяю «MUT» к действию, так что я могу добавить дополнительную логику, я не могу понять, как чтобы получить доступ к тому, что на самом деле хранятся в Собствености «model.selectedEmps»
  2. Даже если я могу понять (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."); 
     } 
    }, 

Таким образом, есть две проблемы решить:

  1. Как получить выбранные сотрудники, итерацию и создавать задания.
  2. Как сохранить результаты в 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 
+0

ли 'employee' модели имеет' belongsTo' отношения с 'trail'? Если это так, я считаю, что запись только хранится в стороне 'ownTo' по умолчанию, поскольку это норма, когда дело касается ORM. – rmmmp

+0

Нет, нет определенного определения. Должен ли я добавить это? – rmcsharry

+0

@MikkoPaderes Я добавил 'ownTo', и это приводит к тому, что массив отношений сотрудников удаляется из json, отправляемого в api. Это имеет смысл, поскольку вы обычно не ожидали, что «trail» создаст конечную точку для получения этого массива и обновит внешние ключи всех этих сотрудников. Хотя я могу представить сценарии, где вы можете этого захотеть. – rmcsharry

ответ

2

проблема окончательного обновления является то, что в 2.x Ember данных, отношения асинхронный по умолчанию, поэтому то, что возвращается с 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'); 
    }); 
}); 

 Смежные вопросы

  • Нет связанных вопросов^_^