Ember2.8: отправка действия из компонента в контроллер

#ember.js

#ember.js

Вопрос:

Читая документацию по Ember, у меня создалось впечатление, что когда действие запускается компонентом, оно будет подниматься по иерархии, пока не достигнет действия с этим именем. Но вот что происходит прямо сейчас. У меня есть компонент игровой карты, написанный следующим образом:

game-card.hbs

 <div class="flipper">
  <div class="front"></div>
  <div class="back">
    <img {{action "proveImAlive"}} src={{symbol}} />
  </div>
</div>
  

game-card.js

 import Ember from 'ember';

    export default Ember.Component.extend({
      classNames: ['flip-container'],
      actions: {
        //blank for now because testing for bubbling up
      }
    });
  

Теперь, согласно тому, что я прочитал, поскольку game-card.js у него нет действия ‘proveImAlive’, он попытается всплыть вверх по иерархии, то есть по контроллеру для конкретного маршрута.

play.js (маршрут /игра)

 import Ember from 'ember';

    export default Ember.Controller.extend({

      actions: {
        proveImAlive() {
          console.log('Im aliiiiveeee');
        }
      }
    });
  

Но когда я, наконец, запускаю свое приложение, я получаю эту ошибку:

 Uncaught Error: Assertion Failed: <testground@component:game-card::ember483> had no action handler for: proveImAlive
  

Теперь мой вопрос двоякий:

  1. Почему возникает эта ошибка?

  2. Я хочу, чтобы некоторые действия моего компонента отображались на контроллере маршрута. Например, при нажатии на игровую карту я хотел бы отправить значение идентификатора (которое будет реализовано) этой карты контроллеру, чтобы он мог сохранить его в массиве.

    щелчок по игровой карте -> отправляет значение 1 -> arrayinController.push(1)

Как я могу этого добиться?

Ответ №1:

Во-первых, я хотел бы отметить, что вы ссылались на документацию Ember v1.10.0. Вам следует ознакомиться с документацией для используемой вами версии Ember, которая, как вы упоминаете, является v2.8.0.

Теперь, согласно тому, что я прочитал, поскольку game-card.js у него нет действия ‘proveImAlive’, он попытается всплыть вверх по иерархии, то есть по контроллеру для конкретного маршрута.

Это не совсем то, что происходит, потому что компоненты изолированы, поэтому нет неявного пузырькования. Когда в руководствах говорится: «действия, отправленные из компонентов, сначала отправляются на контроллер шаблона» и «он отобразится на маршруте шаблона, а затем вверх по иерархии маршрутов», это означает, что вы должны явно отправить действие из компонента. Если компонент вложен в другой компонент, вы должны делать это для каждого уровня, пока не дойдете до контроллера.

  1. Почему возникает эта ошибка?

Вам нужно привязать действие в шаблоне: {{game-card proveImAlive="proveImAlive"}}

  1. я хотел бы отправить значение идентификатора (которое будет реализовано) этой карты контроллеру, чтобы он мог сохранить его в массиве.

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

Я приготовил для вас головоломку.

а) Инициализировать массив в контроллере

 export default Ember.Controller.extend({
  appName: 'Ember Twiddle',
  gameCards: null,

  init() {
    this.set('gameCards', []);
  }
}
  

б) Реализовать действие, которое было передано в массив

 export default Ember.Controller.extend({
  appName: 'Ember Twiddle',
  gameCards: null,

  init() {
    this.set('gameCards', []);
  },

  actions: {
    proveImAlive(cardNo) {
      this.get('gameCards').pushObject(cardNo);
      console.log('Im aliiiiveeee - cardNo', cardNo);
    }
  }
});
  

c) Привязать действие закрытия вниз

 {{game-card proveImAlive=(action 'proveImAlive')}}
  

d) Инициировать действие, передавая аргументы

 <div class="flipper">
  <div class="front"></div>
  <div class="back">
    <button {{action proveImAlive 1}}> ProveIamAlive</button>
  </div>
</div>
  

Комментарии:

1. Большое вам спасибо за ваше объяснение. Это сделало вещи кристально ясными. Приветствия! 🙂

Ответ №2:

Вам необходимо явно задать обработчик действия:

 {{component-name fooAction=fooHandler}}
  

Это необходимо, потому что это помогает сохранить компоненты модульными и повторно используемыми. Неявные ссылки могут привести к тому, что компонент вызовет непреднамеренное поведение.

Ответ №3:

Ваш код должен работать, только если вы включили game-card компонент в play.hbs . Я сомневаюсь, что контроллер для конкретного маршрута не воспроизводится в вашем случае.

Вот рабочий процесс

Вместо действий с пузырьками используйте действия закрытия. Для лучшего понимания вы можете перейти по ссылкам ниже,
https://dockyard.com/blog/2015/10/29/ember-best-practice-stop-bubbling-and-use-closure-actions
http://miguelcamba.com/blog/2016/01/24/ember-closure-actions-in-depth/
https://emberigniter.com/send-action-does-not-fire/

Комментарии:

1. Эй, я хочу отметить, что ваш Twiddle работает из-за ошибки в Ember 2.8.0. Если вы обновитесь до версии Ember 2.8.1, вы получите сообщение об ошибке об отсутствующем обработчике.