使用Meteor制作日历应用程序时发布/订阅问题

时间:2015-04-21 19:26:48

标签: meteor

我正在尝试使用Meteor构建日历应用程序,但是有关于从数据库初始加载数据的问题。

刚开始时,我刚刚使用了autopublish,这导致了问题,因为订阅可能还没有准备好。然后我查看了Can't put data from a Meteor collection into an arrayMeteor: How can I tell when the database is ready?这里的问题,并对我的代码进行了一些更改:

Meteor.startup(function(){
  Session.set("data_loaded", false);
});

Meteor.subscribe("allEvents", function() {
  Session.set("data_loaded", true);
});

var myCalendar = null;

Template.Calendar.onRendered(function() {
  if (Session.get("data_loaded")) {
    myCalendar = $('#myCalendar').fullCalendar({
      header: {
        left: 'prev,next,today',
        center: 'title',
        right: 'month,agendaWeek,agendaDay'
      },
      defaultView: 'agendaWeek',

      dayClick: function(date, jsEvent, view) {
        CalEvents.insert({title:"New Event", start:date.format(), end:date.format()});
        Session.set("lastMod", new Date());
      },
      eventClick: function(calEvent, jsEvent, view) {

      },
      events: function(start, end, timezone, callback) {
        var events = [];
        allEvents = CalEvents.find({},{reactive:false});
        console.log(allEvents);
        allEvents.forEach(function(evt){
          console.log(evt);
          events.push({
            id:evt._id,
            title:evt.title,
            start:evt.start,
            end:evt.end});
        });
        callback(events);
      }
    }).data().fullCalendar;
  }
  myCalendar.defaultView = 'agendaWeek';
});

Template.Calendar.lastMod = function() {
  return Session.get("lastMod");
};

但是,我现在仍然遇到同样的问题,而不是显示空白日历,在大多数情况下它根本不显示日历。我觉得我没有正确设置Session,特别是对于if语句,但我不太确定如何做到这一点。

然后,我发现了这篇文章Displaying loader while meteor collection loads,并按照那里的步骤进行模板级订阅。但是,我又遇到了另一个错误。

var myCalendar = null;

Template.Calendar.onCreated(function(){
  this.subscribe("allEvents");
});

Template.Calendar.onRendered(function() {
    myCalendar = $('#myCalendar').fullCalendar({
      header: {
        left: 'prev,next,today',
        center: 'title',
        right: 'month,agendaWeek,agendaDay'
      },
      defaultView: 'agendaWeek',

      dayClick: function(date, jsEvent, view) {
        CalEvents.insert({title:"New Event", start:date.format(), end:date.format()});
        Session.set("lastMod", new Date());
      },
      eventClick: function(calEvent, jsEvent, view) {

      },
      events: function(start, end, timezone, callback) {
        var events = [];
        allEvents = CalEvents.find({},{reactive:false});
        console.log(allEvents);
        allEvents.forEach(function(evt){
          console.log(evt);
          events.push({
            id:evt._id,
            title:evt.title,
            start:evt.start,
            end:evt.end});
        });
        callback(events);
      }
    }).data().fullCalendar;
  myCalendar.defaultView = 'agendaWeek';
});

Template.Calendar.lastMod = function() {
  return Session.get("lastMod");
};

模板文件:

<template name="Calendar">
  {{#if Template.subscriptionReady}}
    {{> editEvent}}
    <br>
    <br>
    <input type="hidden" name="lastMod" value="{{lastMod}}" id="lastMod">
    <div id="myCalendar">
    </div>
  {{else}}
    Loading...
  {{/if}}
</template>

当应用程序启动时,它显示“正在加载...”字符,但后来我遇到了一个TypeError:无法从}).data().fullCalendar;

读取未定义属性'fullCalendar'

任何人都可以帮我把这件事搞定吗?提前致谢。

1 个答案:

答案 0 :(得分:0)

简短回答:“流星搜索”是你的朋友。使用我在评论中链接的组件。

答案很长:使用流星来获取修改DOM或创建整个DOM树的UI元素非常棘手。整体问题是meteor没有一个回调,当DOM完成时会调用它。事实上,DOM从未最终确定,并且可能随时发生变化。 UI组件创建并位于子树中的任何自定义节点都将被销毁,并且必须重新创建。虽然它可以完成,但它是相当多的管道,并且不容易被新发起的流星理解。

幸运的是,大多数频繁使用的UI组件已经拥有流星智能包,使用它们只需要进行“流星添加”。即使是更有经验的人也更喜欢简单地节省时间,如果一个包已经整理了组件的管道,那么只需要使用它而不是花几个小时试图让它从头开始工作。