Выбор jQuery не работает в Meteor 1.1.0.2 onRendered

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

Мой шаблон (несколько упрощенный)

<template name="formEdit">
  <div id="formContainer">
    {{#if Template.subscriptionsReady}}
      {{#with form this}}
        <table id="headerFieldsTable" class="table">
          <tbody id="headerFields">
            {{#each headerFields}}
              <tr class="headerFieldRow">
                <td>{{> headerFieldViewRow }}</td>
              </tr>
            {{/each}}
          </tbody>
        </table>

        <h5>Form Fields</h5>
        <table id="formFieldsTable" class="table">
          <tbody id="formFields">
            {{#each formFields}}
              <tr class="formFieldRow">
                <td>{{> formFieldViewRow }}</td>
              </tr>
            {{/each}}
          </tbody>
        </table>

      {{/with}}
    {{else}}
      Loading...
    {{/if}}
  </div>
</template>

И шаблон onRendered():

Template.formEdit.onRendered(function() {
  var formsSubscription = this.subscribe('formById', this.data);
  var headerFieldsSubscription = this.subscribe('headerFieldsForForm', this.data);
  var formFieldsSubscription = this.subscribe('formFieldsForForm', this.data);

  var formEditTemplate = this;
  this.autorun(function() {
    if (formsSubscription.ready() && headerFieldsSubscription.ready() && formFieldsSubscription.ready()) {
formEditTemplate.$(''));
      formEditTemplate.$('#headerFields').sortable({
        axis: "y",
        stop: function(event, ui) {
          var headersToSave = [];
          $('#headerFieldsTable div.headerField').each(function(idx, headerFieldDiv) {
            var header = Blaze.getData(headerFieldDiv);
            header.sequence = idx;
            headersToSave.push(header);
          });
          _.each(headersToSave, function(header) { header.save(); });
        }
      });

      formEditTemplate.$('#formFields').sortable({
        axis: "y",
        stop: function(event, ui) {
          var feildsToSave = [];
          $('#formFieldsTable div.formField').each(function(idx, formFieldDiv) {
            var field = Blaze.getData(formFieldDiv);
            field.sequence = idx;
            feildsToSave.push(field);
          });
          _.each(feildsToSave, function(field) { field.save(); });
        }
      });
    }
  });
});

Но как для верхних, так и для нижних колонтитулов formEditTemplate.$('#headerFields') и formEditTemplate.$('#formFields'), похоже, не возвращают результатов. Кажется, что DOM на самом деле нет. Я думал, что вызов .ready() для всех подписок исправит это, но думаю, что есть проблема со временем, когда Blaze еще не исправил DOM, но подписки действительно сделаны. Я говорю это, потому что я поставил точку останова в Chrome прямо в первой строке if, а браузер все еще показывал «Загрузка…».

Я также попытался связать вещи, наняв помощника, который устанавливал сортировку, помещенную в конец блока {{#with}}, надеясь, что, возможно, она будет отображаться последней, но это тоже не сработало.

Я нашел несколько статей на форумах Meteor, которые, казалось, предлагали добавить таймер, но это кажется очень «хакерским». Есть ли новый шаблон для запуска JS, требующий полной инициализации DOM?


person CodeChimp    schedule 26.07.2015    source источник


Ответы (1)


Вместо временной задержки я рекомендую вам использовать Tracker.afterFlush(), чтобы гарантировать, что DOM был создан и обновлен. Вот описание из документации Meteor:

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

Итак, внутри вашего оператора if вы можете обернуть блок кода следующим образом

if (formsSubscription.ready() && headerFieldsSubscription.ready() && formFieldsSubscription.ready()) {
  Tracker.afterFlush( function () {
    //Code block to be executed after subscriptions ready AND DOM updated
  });
}

Здесь приведена ссылка с примерами использования Tracker.afterFlush.

person FullStack    schedule 27.07.2015
comment
Не знаю, почему я всегда забываю, что Tracker.afterFlush() существует. Спасибо, это сработало отлично. - person CodeChimp; 28.07.2015