Meteor.js: как вызвать вспомогательный метод из события?

Я подозреваю, что не делаю этого способом Метеор. Я делаю общий интерактивный календарь.

У меня есть шаблон календаря:

<template name="calendar">
<h2>Calendar</h2>
<div class="calendar">{{#each days}}
    {{> day}}
    {{/each}}
</div>
</template>

С помощником, который возвращает объект дня:

     {
        date: thisDate.getDate(),
        dateString: dateString,
        done: done,
        today: isToday
      }

У меня есть шаблон дня:

<template name="day">
  <div class="day {{stateString}}">{{date}}</div>
</template>

С некоторыми помощниками (meetingID теперь жестко запрограммирован для разработки):

  Template.day.helpers({
    state: function(){
      // retreive from DB
      var s = Meetings.findOne({"_id":meetingID}).dates[this.dateString];
      return s;
    }
    stateString: function(){
      var stateString;

      switch(this.state){
        case -1: stateString = "unknown"; break;
        case 0: stateString = "unavailable"; break;
        case 1: stateString = "available"; break;
      }
      if(this.done) stateString = "done";

      return stateString;
    }
  });

state() получает состояние из db, а stateString() выбирает правильное имя класса для этого состояния.

Когда вы нажимаете на него, вы циклически переключаете состояния (1: доступно, 0: недоступно, -1: неизвестно):

  Template.day.events({
    "click": function(){
      if(this.done) return false;   // no state changes for past days!
      console.log(e);
      var newState = this.state + 1;
      if(newState > 1) newState = -1;

      var q = "dates."+this.dateString+"."+Meteor.userId()+".state";
      console.log(q+ " / "+this.state+" / "+newState);
      Meetings.update(meetingID, {$set:{q:newState}});

      return false;
    }
  })

У меня есть как минимум две проблемы:

1) Как мне вызвать помощника state() из события click? 2) Мое обновление db не работает - оно создает документ "q" вместо использования строки, хранящейся в q.

Я уверен, что это не дает основополагающего понимания правильного пути для этого - пожалуйста, помогите!

Ответ 1

Просто расширяем ответ на @mark. Вероятно, вы хотите сохранить state в качестве реактивной переменной, чтобы хелпер stateString обновлялся при изменении состояния. Если я правильно понимаю, вы на самом деле не пытаетесь использовать помощник state в своем шаблоне - это просто необходимо для помощника строки и события. Сначала добавьте пакет reactive-var:

meteor add reactive-var

Я бы рекомендовал сделать что-то вроде этого для вашего шаблона:

Template.day.created = function() {
  this.state = new ReactiveVar();
  this.autorun(_.bind(function() {
    var meetingDates = Meetings.findOne(meetingID).dates[this.data.dateString];
    var currentState = meetingDates[Meteor.userId()].state;
    this.state.set(currentState);
  }, this);
};

Template.day.helpers({
  stateString: function() {
    if (this.done) {
      return 'done';
    }
    switch(Template.instance().state.get()) {
      case -1: return 'unknown';
      case 0: return 'unavailable';
      case 1: return 'available';
    }
  }
});

Template.day.events({
  'click': function(event, template) {
    if (this.done) {
      return;
    }

    var newState = template.state.get() + 1;
    if (newState > 1) {
      newState = -1;
    }

    var modifier = {$set: {}}
    modifier.$set['dates.'+this.dateString+'.'+Meteor.userId()+'.state'] = newState;

    Meetings.update(meetingID, modifier);
  }
});

Ответ 2

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

Template.day.created = function () {
  // here `this` refers to template instance
  this.state = -1;
};

Template.day.helpers({
  state: function () {
    var s = Meetings.findOne({"_id":meetingID}).dates[this.dateString];
    Template.instance().state = s;
    return s;
  },
  ...
});

Template.day.events({
  'click': function () {
    ...
    var state = Template.instance().state;
    ...
  }
});

Что касается проблемы с q, вам нужно сначала создать объект, иначе q будет интерпретироваться как фактическое имя поля, а не переменная (обратите внимание, как не существует различия между "q" и q внутри запрос).

var query = {};
query[q] = newState;
Meetings.update(meetingID, { $set: query });

Надеюсь, это поможет!

Ответ 3

Доступ к помощникам шаблонов доступа из любого места:

Template.<name>.__helpers.get('<helper>').call()