Как обрабатывать и отображать вложенные отношения данных hasMany в Ember - PullRequest
0 голосов
/ 24 мая 2018

Проблема:

Я не могу понять, как обрабатывать и затем отображать вложенные записи Ember Data в компоненте.

Я не знаю, как другиеподойти к этой проблеме, и если я упускаю что-то решающее в Эмбер, которое предотвращает проблему.Я думаю, что с тем, как я использую обещания, может произойти странная логическая невозможность, поскольку очевидно, что они недостаточно хорошо понимают их.

Справочная информация:

Ясоздание веб-приложения для спортивных соревнований.Соревнования разбиты на дни, которые имеют события.Спортсмены соревнуются в этих соревнованиях, и их данные о производительности сохраняются в записях, в частности, в набранных очках.

Мне нужно отобразить табло на определенный день.Табло, по сути, представляет собой таблицу результатов спортсменов для каждого события в этот день.Например: Image of the scoreboard table Что я пробовал:

  • Реализация подобной логики в контроллере множеством различных способов.
  • Попытка переместить логику на маршрут, но возникли аналогичные проблемы.
  • Поиск в Интернете.
  • Восстановление.

Код контроллера (некорректная логика):

приложение / компоненты / интерфейс ввода данных / день / табло-интерфейс-row.js

export default Component.extend({
  store: Ember.inject.service(),
  tagName: '',
  eventScores: Ember.computed('day.events.@each.records.@each.{points,athlete.id}', async function () {
    let day = this.get('day');
    let eventScoresPromises = await day.get('events').map(async event => {
      let recordsPromises = await event.get('records').map(record => record);
      let records = await Promise.all(recordsPromises);
      return await records
        .filter(record => record.get('athlete.id') === this.get('athlete.id'))
        .map(record => record.get('points'));
    });
    return await Promise.all(eventScoresPromises);
  }),
});

Код управления маршрутом(только для справки):

app / router.js

Router.map(function () {
  this.route('competition-list-interface');
  this.route('data-entry-interface', {
    path: '/data-entry-interface/competition/:competition_ID'
  }, function () {
    this.route('day', {
        path: '/day/:day_ID'
      },
      function () {
        this.route('scoreboard-interface', {
          path: '/scoreboard'
        });
      });
  });
});

app / routs / data-entry-interface.js

async model(params) {
    let competition = await this.store.findRecord('competition', params.competition_ID);
    let days = await competition.get('days');
    return {
      competition: competition,
      days: days,
    }
  }

приложение / маршруты / интерфейс ввода данных / day.js

async model(params) {
    let day = await this.store.findRecord('day', params.day_ID);
    let competition = this.modelFor('data-entry-interface').competition;
    return {
      day: day,
      athletes: competition.athletes,
      competition: competition,
    }
  }

приложение / маршруты / ввод данных-interface / day / Scoreboard-interface.js

model() {
    let competition = this.modelFor('data-entry-interface').competition;
    let day = this.modelFor('data-entry-interface/day').day;
    let athletes = competition.get('athletes');

    return Ember.RSVP.hash({
      competition: this.modelFor('data-entry-interface').competition,
      day: this.modelFor('data-entry-interface/day').day,
      athletes: athletes,
    });
  },
  setupController(controller, model) {
    controller.set('model', model);
  }

Шаблонный код (только для справки):

app / templates / data-вход-интерфейс / день / табло-интерфейс.hbs

<table class="table table-hover table-striped table-bordered">
<thead>
<tr>
  <td>Athlete {{model.scoreBoardRows}}</td>
  {{#each model.day.events as |event|}}
    <td>Points for event: {{event.name}}</td>
  {{/each}}
  <td>Total points for day {{model.day.number}}</td>
  <td>Positions for day {{model.day.number}}</td>
</tr>
</thead>
<tbody>
{{#each model.athletes as |athlete|}}
  {{data-entry-interface/day/scoreboard-interface-row athlete=athlete day=model.day}}
{{/each}}
</tbody>

app / templates / components / data-input-interface / day / Scoreboard-interface-row.hbs

<tr>
    <td>{{athlete.name}}</td>
    {{#each eventScores as |eventScore|}}
        <td>{{eventScore}}</td>
    {{/each}}
    <td>{{totalPointsForDay}}</td>
    <td>{{overallPositionForDay}}</td>
</tr>

Технические подробности:

  • Использование FireBase длясохранить данные и разместить сайт.Я использую библиотеку EmberFire (V2.0.9) для операций CRUD, которая работает со встроенной нормальной библиотекой EmberData (V3.1.0)
  • EmberCli - версия V3.1.4, а EmberSource - версия V3.1.0

Исследования, которые я провел:

  • Аналогичный вопрос за исключением того, что они просто отображают вложенные данные
  • Пост , который, кажется, почти точно то, что мне нужно, но, кажется, не работает для меня
  • Пост , объясняющий обещания для подобной аналогичной проблемы

1 Ответ

0 голосов
/ 25 мая 2018

Есть проблема с вашей вычисленной функцией в вашем контроллере.Чтобы процитировать цитаты из документов Ember относительно агрегатных вычисляемых свойств: «Обратите внимание, что @each работает только на один уровень глубиной. Вы не можете использовать вложенные формы, такие как todos. @ Each.owner.name или todos. @ Each.owner. @ Each.name.»См. Документы Ember здесь: https://guides.emberjs.com/v3.1.0/object-model/computed-properties-and-aggregate-data/#toc_code-each-code.

Помимо этой ошибки, кажется, что у вас есть смысл ... хотя раньше я не использовал подход async model(), чтобы узнать, может ли это также вызвать осложнения.ember-concurrency может быть хорошим вариантом, чтобы дать вам больше контроля над вашими данными.

...