Ember.JS создает запись в компоненте и добавляет в локальное хранилище данных или передовое решение

Текущая ситуация: я пытаюсь найти способ создать запись конкретной модели из метода "didInsertElement" компонента и добавить указанные данные в хранилище данных.

Причина текущей ситуации: я прикрепляю прослушиватели событий к кнопке в файле компонента HBS. Одна из кнопок вызовет два каскадных, но легких вызова ajax. Ответ от последнего из этих вызовов ajax определит, должен ли я создавать записи или нет.

Проблема, с которой я столкнулся: когда я пытаюсь получить доступ к хранилищу из компонента следующим образом:

var myStore = this.store

Я получаю неопределенный объект. Для тех из вас, кто спрашивает, я уже добавил следующую строку в свой компонент:

store: Ember.inject.service()

И у меня уже установлен Ember-Data.

Решения. Многочисленные исследования показали, что взаимодействие с магазином лучше всего осуществлять по основному маршруту. Но как мне прикрепить прослушиватели событий к виджету jquery компонента из маршрута?

Существуют ли какие-либо решения, которые не потребовали бы от меня перемещения всего кода прослушивателя событий из компонента в маршрут и, таким образом, отказа от модульности, которую должен предлагать ember?


person Tom Mathew    schedule 07.09.2016    source источник


Ответы (1)


this.store существует в элементах, в которые оно было введено по умолчанию (контроллеры и маршруты), и, вероятно, его не следует использовать, поскольку оно пропускает геттеры, которые являются неотъемлемой частью Ember.

Правильный способ доступа к нему в компоненте (при условии, что вы его ввели) через:

this.get('store')

Из множества исследований я обнаружил, что взаимодействие с магазином лучше всего осуществлять через основной маршрут.

Вы, вероятно, захотите (по крайней мере, в большинстве случаев) получить доступ к данным хранилища не на основном маршруте, а в контроллере, в котором существует ваш компонент, а затем просто передать данные в компонент.

На это есть несколько причин:

  • Маршруты в основном используются для получения данных и управления механизмом маршрутизации вашего приложения, куда переходит пользователь, в каких точках происходит переход и почему и т. д. Маршруты не должны контролировать, какие данные отображаются и как, только как/когда его получили.
  • Контроллеры в основном используются для обработки данных, подготовки, преобразования и т. д. Сюда входят такие вещи, как фильтрация данных, их сортировка, извлечение подмножества и т. д.
  • Данные контроллера доступны непосредственно в шаблонах, а данные маршрута — нет.

Хук setupController() в Ember.Route фактически делает это по умолчанию. .

Это операция по умолчанию, выполняемая в хуке setupController():

set(controller, 'model', model);

Таким образом, ваш контроллер по умолчанию имеет доступ к модели и может затем передать ее компонентам.

Таким образом вы четко отделяете логику, которая извлекает/получает/обрабатывает данные, от логики, которая их отображает.

Я прикрепляю прослушиватели событий к кнопке в моем компонентном файле HBS. Одна из кнопок вызовет два каскадных, но легких вызова ajax. Ответ от последнего из этих вызовов ajax определит, должен ли я создавать записи или нет.

Естественный способ сделать это в Ember — прикрепить действие к вашей кнопке, которое будет просто распространяться на контроллер.

// inside components/example.js
// ...
actions: {
  myButtonAction() {
    // call the controller action
    this.get('controllerActionThatWasPassedIn')(/* pass any data if necessary */);
  }
}

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

// controllers/example.js
// ...
actions: {
  handleData(someArgs) {
    this.get('store)'.findSomething(someArgs).then((result) => {
      this.set('result', result); // set the result which will automatically be passed down into the component
    });
  }
}

// templates/example.hbs
{{my-component result=result
               controllerActionThatWasPassedIn=(action "handleData")
}}

В Ember эта концепция называется Данные. вниз, Действия вверх.

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

// inside components/example.js
// ...
actions: {
  myButtonAction() {
    // call the controller action
    this.get('controllerActionThatWasPassedIn')(/* pass any data if necessary */)
      .then((result) => {
        // do stuff with result
      });
  }
}

Как мне прикрепить прослушиватели событий к виджету jquery компонента из маршрута?

Примечание: анти-шаблон

В Ember нет естественного способа сделать это, в основном потому, что маршруты и контроллеры создаются до того, как что-либо будет отрисовано. Вот почему вы не хотели бы делать это в маршруте и в контроллере.

Однако, если вам, возможно, не нужен контроллер и вы хотите только выполнить какую-то быструю/небольшую операцию DOM в маршруте (обратите внимание, что это обычно анти-шаблон), вы всегда можете использовать Ember Run Loop перехватывает и планирует выполнение некоторых операций после рендеринга:

export default Ember.Route.extend({
  init() {
    this._super(...arguments);

    Ember.run.scheduleOnce('afterRender', () => {
      $('.my-component').click(/* ... */)
    });
  }
});

Или вы можете сделать это непосредственно в хуке renderTemplate() после того, как вы визуализировать содержимое:

renderTemplate() {
  this.render();
  $('.my-component').click(/* ... */); // Probably shouldn't do this though
}
person nem035    schedule 07.09.2016
comment
Кажется, я не могу использовать this.get. Я получаю сообщение об ошибке, что get не является функцией. Когда я регистрирую, что это такое, я вижу, что это объект ajax. Я понимаю, что это потому, что я выполняю свою логику в своем обратном вызове Success в ajax. Но когда я жду ответа вне объекта ajax, я никогда не получаю данные. Есть ли решение для 1. Проникновение моих данных ответа обратно из каскадных вызовов ajax, как-то дождаться ответа, а затем получить доступ к хранилищу? или 2. Somehome получить доступ к магазину из обратного вызова успеха AJAX - person Tom Mathew; 07.09.2016
comment
Какая именно у вас проблема? Вот простая демонстрация ember-twiddle - person nem035; 07.09.2016
comment
Ваша проблема — обычная проблема JS, а не проблема Ember. Это проблема переопределения контекста функции (this) в обратных вызовах. В основном это решается либо: 1. сохранением this в переменной перед обратными вызовами (т. е. шаблоном var self = this), что потребует от вас выполнения self.get... в вашем обратном вызове, либо просто использованием функция стрелки в качестве обратного вызова, которая поддерживает контекст своей внешней области, поэтому вы можете выполнять this.get... - person nem035; 07.09.2016
comment
Подход, который я бы предложил, состоит в том, чтобы вообще не использовать ajax jQuery, а внедрить ember-ajax как услуга, которая является обещанной, скорректированной вариацией $.ajax. При этом код становится намного лучше и проще, например, вы можете просто сделать this.get('ajax')(/* ajax options */).then((ajaxResponse) => this.get('store').doStuff(), чтобы получить то, что вам нужно. - person nem035; 07.09.2016
comment
Вы были абсолютно правы в том, что это проблема JS. Как только я поддержал составленное определение компонента (т.е. не принял как должное, что это = контекст компонента), эта проблема исчезла. Я посмотрю ember-ajax, но решил сделать это позже. Еще раз спасибо!! - person Tom Mathew; 07.09.2016
comment
Ничего страшного, дружище, рад помочь :) - person nem035; 07.09.2016