流星。如何从事件调用helper方法?

时间:2020-12-29 06:59:08

I suspect I'm not doing this the Meteor way. I'm making a shared, interactive calendar.

我怀疑我不是像流星一样。我正在制作一个共享的互动日历。

I have a calendar template:

我有一个日历模板:

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

With a helper that returns a day object:

使用一个返回日对象的助手:

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

I have a day template:

我有一天的模板:

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

With some helpers (meetingID is hardcoded for now for development):

有一些助手(会议id现在已经硬编码用于开发):

  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() gets the state from the db and stateString() picks the right class name for that state.

state()从db获取状态,stateString()为该状态选择正确的类名。

When you click on it, you cycle through states (1: available, 0: not available, -1: unknown):

当你点击它,你循环通过状态(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;
    }
  })

I'm having at least two specific problems:

我至少有两个具体问题:

1) How do I call the state() helper from the click event? 2) My db update doesn't seem to work—it's creating a 'q' document instead of using the string stored in q.

1)如何从单击事件调用state() helper ?2)我的db更新似乎不起作用——它正在创建一个“q”文档,而不是使用存储在q中的字符串。

I'm sure this is missing some fundamental understanding of the right way to do this—please help!

我确信这缺少了对正确方法的一些基本理解——请帮助!

3 个解决方案

#1


5  

Just expanding on the answer by @mark. You probably want to store state as a reactive variable so that your stateString helper will update when the state changes. If I understand correctly, you are not actually trying to use the state helper in your template - it is just needed for the string helper and the event. First add the reactive-var package:

我只是扩展一下@mark的答案。您可能希望将状态存储为一个反应性变量,以便当状态发生更改时,您的stateString helper可以进行更新。如果我理解正确,您实际上并没有试图在模板中使用状态助手——它只是字符串助手和事件所需要的。首先添加reactive-var包:

meteor add reactive-var

I would recommend doing something like this for your template:

我建议您为模板做这样的事情:

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


3  

Off the top of my head, one way to persist data between helpers and events in the same template is to store it as a property inside the template instance. So for example, you might have something that looks like this:

在我的头脑中,在帮助器和相同模板中的事件之间持久化数据的一种方法是将它作为一个属性存储在模板实例中。例如,你可能有这样的东西

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;
    ...
  }
});

As for the issue with q, you have to construct the object prior, otherwise q will be interpreted as the actual field name rather than a variable (notice how there's no distinction between "q" and q inside the query).

对于q的问题,您必须先构造对象,否则q将被解释为实际的字段名而不是变量(请注意查询中“q”和q之间没有区别)。

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

Hope this helps!

希望这可以帮助!

#3


3  

Access template helpers from anywhere:

从任何地方访问模板助手:

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

#1


5  

Just expanding on the answer by @mark. You probably want to store state as a reactive variable so that your stateString helper will update when the state changes. If I understand correctly, you are not actually trying to use the state helper in your template - it is just needed for the string helper and the event. First add the reactive-var package:

我只是扩展一下@mark的答案。您可能希望将状态存储为一个反应性变量,以便当状态发生更改时,您的stateString helper可以进行更新。如果我理解正确,您实际上并没有试图在模板中使用状态助手——它只是字符串助手和事件所需要的。首先添加reactive-var包:

meteor add reactive-var

I would recommend doing something like this for your template:

我建议您为模板做这样的事情:

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


3  

Off the top of my head, one way to persist data between helpers and events in the same template is to store it as a property inside the template instance. So for example, you might have something that looks like this:

在我的头脑中,在帮助器和相同模板中的事件之间持久化数据的一种方法是将它作为一个属性存储在模板实例中。例如,你可能有这样的东西

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;
    ...
  }
});

As for the issue with q, you have to construct the object prior, otherwise q will be interpreted as the actual field name rather than a variable (notice how there's no distinction between "q" and q inside the query).

对于q的问题,您必须先构造对象,否则q将被解释为实际的字段名而不是变量(请注意查询中“q”和q之间没有区别)。

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

Hope this helps!

希望这可以帮助!

#3


3  

Access template helpers from anywhere:

从任何地方访问模板助手:

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